文章目录
- 什么是Docker
- Docker的优势
- Docker的原理
- Docker 的安装
- Docker 的 `namespaces`
- Docker的常见命令
- `docker version`:查看版本信息
- `docker info `查看docker详细信息
- 我们关注的信息
- `docker search`:镜像搜索
- `docker pull`:镜像拉取到本地
- `docker push`:推送本地镜像到镜像仓库
- `docker tag`:为镜像加(改)标签
- `docker login`:登录镜像仓库
- `docker run`:启动一个镜像(容器)
- 前台启动
- 后台启动
- 【补】为什么我们上面两个容器,最后都会退出?
- 【补】那我们怎么解决这个问题呢?
- 1.既然我们直接不管他不行,那就先这个bash终端放到后台瞧瞧
- 2.我们再来瞧瞧,是不是哪里理解错了
- 我们再启动一个nginx容器试试
- 问题来了,我们启用nginx容器的目的不是要做个网站吗,我们只知道容器内部用的是80端口,那我们在宿主机怎么访问呢?
- 总结一下
- `docker ps`:查看容器信息
- `docker logs`:查看容器日志
- 【补】除了用docker logs命令,我们还可以直接进入容器的上下文目录查看日志
- `docker exec`:进入(正在运行的)指定容器
- `docker cp`:文件的拷贝
- 将本地文件(宿主机文件)拷入容器中
- 将容器中的文件拷贝到宿主机中
- `docker rmi`:删除镜像
- `docker rm`:删除容器
- `docker stop`:停止容器
- `docker start`:重启容器
- `docker history`:查看镜像更改记录
- `docker commit`:提交容器状态为镜像到本地仓库
- 我们再看看这个镜像的细节
- 用这个镜像起一个容器
- 在另一个窗口看看
- 我们回到这个终端,退出容器试试
- `docker build`:通过Dockerfile 构建镜像
什么是Docker
百度百科
Docker的优势
-
跨平台部署:Docker 可以在不同的操作系统和硬件平台上运行,可以轻松地将应用程序在开发、测试和生产环境中进行一致性的部署。
-
资源利用率和扩展性:Docker 可以通过容器的方式将应用程序与其依赖的运行时环境和依赖项隔离,从而提高资源的利用率并减少资源的消耗。此外,Docker 还支持快速水平扩展,使应用程序能够更好地适应变化的负载。
-
快速交付和部署:通过 Docker 容器化,可以实现快速的应用程序交付和部署。将应用程序和其依赖项打包到容器中,可以确保运行环境的一致性,并且在不同的环境中轻松地部署和迁移应用程序。
-
简化开发环境配置:Docker 可以帮助开发人员更轻松地配置开发环境。通过使用容器,可以将应用程序及其依赖项打包到一个镜像中,并在开发环境中进行部署,从而减少了由于开发环境配置不一致导致的问题。
-
提高应用程序的安全性:Docker 的容器隔离技术可以将应用程序与底层主机隔离开来,从而提高应用程序的安全性。每个容器都有自己的文件系统、进程空间和网络接口,使得应用程序之间互不干扰。
Docker的原理
我们现在可以知道Docker实际上就是一个应用程序,只不过自己带上了所需要的依赖。在考虑Docker的原理之前,我们先来看看在部署应用的方式是怎样一步步升级的
以部署一个Mysql程序为例
-
物理机
-
首先,我们要拥有一个操作系统(通常是Linux操作系统)
-
安装依赖环境(gcc、make、libncurses5-dev等编译工具)
-
安装应用程序
此时如果我们要增加一台新的物理机来处理Mysql并发请求,就需要再进行一次环境的重复配置
-
-
虚拟化(KVM或其他技术)
- 将一个物理机虚拟成多个机器
- 可以将依赖环境打包成一个模板(VMware Workstation的克隆功能就是这样实现的)
-
容器化
-
以镜像为基础
- 依赖环境的镜像
- Java程序——Java的基础镜像
- Php程序——Php的基础镜像
- Nginx程序——Linux操作系统基础镜像
- 根据基础镜像——放入自己的代码(或包)——>生成程序镜像
- 依赖环境的镜像
-
镜像按层存储
这样的方式可以让我们使用同于基础层来实现不同的功能,如上图,下面两层我们就可以直接套用模板了
-
启动时间快(秒级启动)
由于与主机共享内核,不需要做操作系统的引导
-
可移植性好
将运行某个应用所需要的环境全部打包到同一个容器中,不需要考虑兼容问题
如上图
- Docker将用户程序与所需要调用的系统函数库一起打包
- Docker运行到不同操作系统时,直接基于打包的函数库,借助于操作系统的Linux内核来运行
-
Docker 的安装
参考官方文档
Docker 的 namespaces
Docker 使用 Linux 内核的 namespaces
功能来实现容器的隔离。namespaces
是 Linux 内核提供的一种机制,用于隔离系统资源,使得运行在不同 namespaces
中的进程拥有独立的视图和环境,而不会相互干扰。Docker 利用这一机制来创建轻量级的虚拟化环境,即容器。
-
进程命名空间(PID Namespace)
进程命名空间允许容器中的进程拥有独立的进程树。这意味着容器内的进程ID(PID)与宿主机或其他容器中的进程ID是隔离的。每个容器都有自己的 PID 1,即容器内的第一个进程。
-
网络命名空间(NET Namespace)
网络命名空间为每个容器提供独立的网络堆栈。容器拥有自己的网络接口、IP地址、路由表、防火墙规则等。这允许容器之间以及容器与宿主机之间进行隔离的网络通信。
-
挂载命名空间(MNT Namespace)
挂载命名空间为每个容器提供独立的文件系统视图。容器可以有自己的
/
根目录,以及独立的挂载点,使得容器可以有自己独特的文件系统结构,而不会影响到宿主机或其他容器。 -
用户命名空间(USER Namespace)
用户命名空间允许容器内的用户和组ID与宿主机上的用户和组ID不同。这意味着容器内的用户可以映射到宿主机上的不同用户,从而提供额外的安全隔离。
-
UTS命名空间
UTS命名空间允许容器拥有独立的主机名和NIS域名。这使得容器可以拥有自己的标识,而不需要与宿主机或其他容器共享。
-
IPC命名空间
IPC命名空间(Inter-process communication namespace)为容器提供独立的进程间通信资源,如消息队列、信号量和共享内存。这确保了容器之间的进程通信是隔离的。
通过这些 namespaces
,Docker 实现了容器的隔离,使得每个容器都像是在独立的环境中运行,而实际上它们共享宿主机的内核。这种隔离机制是容器轻量级和高效的关键
Docker的常见命令
docker version
:查看版本信息
- Docker版本
Version: 24.0.7
- 宿主机架构
OS/Arch:linux/amd64
- 其他一些关键组件的版本
docker info
查看docker详细信息
我们关注的信息
-
Client Debug Mode
:false #客户端的debug模式,按需开启 -
Server: Containers: 1 # 已构建1个容器 Running: 0 # 正在运行的容器数量 Paused: 0 Stopped: 1 Images: 3 # 服务器保存的镜像数量
docker ps -a
docker images
-
Storage Driver: overlay2
存储驱动为overlay2(官方默认、性能好)常见驱动 aufs、overlay、brtfs
-
Logging Driver: json-file
:Docker 日志存储类型#json-file存储在本地的Docker根目录
-
Docker Root Dir: /var/lib/docker
:Docker根目录(可以更改)#最好使用一个单独的磁盘挂载该目录
-
Runtimes: runc io.containerd.runc.v2
:容器创建、销毁以及运行都是调用Runtime来执行 -
Live Restore Enabled: false
:开启后自动重启容器
docker search
:镜像搜索
带officials为官方镜像
docker pull
:镜像拉取到本地
-
本地有同一镜像,则不会重复拉取
-
docker pull xxx.com/nginx:latest
#从xxx.com的镜像仓库拉取标签为latest的nginx镜像;不加URL则表示从官网拉取
-
不加标签默认拉取最新版本
docker push
:推送本地镜像到镜像仓库
docker push xxx.com/my-namespace/my-nginx:latest
docker tag
:为镜像加(改)标签
dockertag my-nginx:latest xx.com/my-namespace/my-nginx:latest
docker login
:登录镜像仓库
-
不加仓库地址默认登陆官方镜像仓库
docker login registry.cn-hangzhou.aliyuncs.com
#登陆阿里云镜像站
docker run
:启动一个镜像(容器)
前台启动
docker run -ti centos:7 bash
# -ti:生成一个终端
# bash:指定终端为bash
后台启动
docker run -d centos:7 bash
【补】为什么我们上面两个容器,最后都会退出?
docker ps -a
我们先来看看他们创建的命令都是docker run xxx bash
,最后都会生成一个终端
我们再到百度上搜搜看什么叫终端
咦,这一切不都说得通了,我们在前台启动的centos7容器是因为退出了容器bash前台终端,这个容器存在的意义也就没了,而后台启动的第二个容器,压根就没前台终端生成。
【补】那我们怎么解决这个问题呢?
1.既然我们直接不管他不行,那就先这个bash终端放到后台瞧瞧
docker run -d centos:7 bash&
表面上看是行了,我们再打开一个窗口看看现在这个容器在不在运行
结果还是不行,out
2.我们再来瞧瞧,是不是哪里理解错了
哦,那我们把这个bash换成其他的不需要前台输入的的命令试试
docker run -d centos:7 tail -f /dev/null
# 这里我们把这个容器当成生产队的驴来用了,持续读取一个空文件的尾部
看看结果,up!!!
docker run -d centos:7 sleep infinity
# 这里用sleep infinity 命令让容器宝宝独自等待~
嗨呀,小case啦,轻轻松松^_*
我们再启动一个nginx容器试试
docker run -d --name nginx_test nginx:test
# --name 指定容器名 后面跟依赖的镜像
问题来了,我们启用nginx容器的目的不是要做个网站吗,我们只知道容器内部用的是80端口,那我们在宿主机怎么访问呢?
-
我们先把他关了
docker stop nginx_test
-
重新启动容器并添加端口映射
docker run -d --name nginx_test -p 8080:80 nginx:test
这是肿么肥四,重名了?我们来看看
docker ps -a
不还是你吗?你小子不听话就把你删了
docker rm nginx_test
接下来把所有的爱给他同父同母的同名兄弟
docker run -d --name nginx_test -p 8080:80 nginx:test # -p [宿主机端口:容器端口] 添加端口映射
-
再用宿主机的8080端口访问一下
这不又好了吗,easy啊~_-
总结一下
bash可以换成任意命令
- 如果是需要前台输入的命令,你得提供一个前台伪终端,提供内容给他
- 后台可以直接运行的命令就无所谓了
docker ps
:查看容器信息
-
docker ps
:查看当前正在运行的容器docker ps
-
docker ps -a
:查看所有已经创建的容器(包括退出)docker ps -a
-
docker ps -q
:查看所有正在运行的容器ID(个人认为用处不大,不如docker ps) -
docker ps -aq
:查看容器的ID(同理用处不大,不如docker ps -a)
docker logs
:查看容器日志
docker logs [容器名/容器ID]
docker logs -f [容器名] # 跟随模式,持续输出,动态查看,用户手动停止
我们来查看刚刚创建的nginx容器日志
docker logs nginx_test
【补】除了用docker logs命令,我们还可以直接进入容器的上下文目录查看日志
sudo su # 进入容器日志目录需要管理员权限
cd /var/lib/docker/containers/
这几个就是目前存在的容器
我们要看nginx容器的日志
cd 969d3c0012a74aa61284fe89be08fcfc17c83ac83674bed422e7b2fc086eb782/
# 不用敲全,用tab补全就行了
ls
tail 969d3c0012a74aa61284fe89be08fcfc17c83ac83674bed422e7b2fc086eb782-json.log
# 结果跟docker logs nginx_test 结果一样一样的
docker exec
:进入(正在运行的)指定容器
docker exec -it nginx_test bash
ls #查看容器内的文件
uname -a #查看容器内部运行的操作系统
exit #退出容器
#进入容器后注意主机名和用户的变化
docker cp
:文件的拷贝
docker cp [宿主机文件] [容器名(或者id):容器内部文件夹(或文件)]
docker cp [容器名(或者id):容器内部文件夹(或文件)]
将本地文件(宿主机文件)拷入容器中
在执行操作前我们先看看nginx的网页存放的位置
find . -name "html"
#莫名其妙的权限报错这会儿咱们就不管了
echo "hello nginx" > index.html&&cat inidex.html
docker cp index.html nginx_test:/usr/share/nginx/html/
这时我们再来看看nginx的主页什么样了
将容器中的文件拷贝到宿主机中
#先在根目录下执行ls命令并将结果重定向到test.txt中
ls >>test.txt
#在宿主机执行cp命令,并显示文件内容
docker cp nginx_test:./test.txt ls_test.txt&&cat ls_test.txt
docker rmi
:删除镜像
我们先看看机子上现有哪些镜像
docker images
居然有两个不知道什么内容的镜像,那把他俩都删了吧,红尘作伴,潇潇洒洒,说干就干
docker rmi 2a36393edaf1 605c77e624dd
再看看,已经不在了
docker rm
:删除容器
我们先来看看有哪些容器不乖了
好嘞,就决定是你了,你都退出了,那我就对你不客气咯
docker rm [容器名(或容器ID)]
docker rm inspiring_shannon
害群之马没啦,一片祥和
docker stop
:停止容器
docker stop [容器名/容器ID]
docker ps
docker stop nginx_test
docker ps
docker start
:重启容器
docker stop [容器名/容器ID]
docker ps
docker start nginx_test
docker ps
docker history
:查看镜像更改记录
我们先看看有哪些镜像
docker images
docker history centos:latest
# 我们选择占用空间最大的centos:latest来看
docker commit
:提交容器状态为镜像到本地仓库
docker commit <参数> <容器id> <仓库>[:标签]>
# -a, --author:指定作者信息,格式为 name <email>。
# -c, --change:应用 Dockerfile 指令到创建的镜像。
# -m, --message:提交信息,描述这次提交的更改。
# --pause:是否在提交时暂停容器,默认为 true
docker commit -a "yy" -m "my_nginx_test_images1" nginx_test my_nginx:v1.0
# -a 参数一般是告诉别人作者的信息,我在这只是本地使用提交,其实加不加无所谓
我们再看看这个镜像的细节
docker history my_nginx
显示了提交时的信息
用这个镜像起一个容器
docker run -it --rm --name nginx_test1 mynginx:v1.0 bash
在另一个窗口看看
docker ps
成功了
我们回到这个终端,退出容器试试
exit
docker ps
咦,nginx_test1怎么没了,是不是退出啦?
我们再看看
docker ps -a
还是没有啊,燕子,没有你我怎么活呀
这时候一旁看戏的nginx_test就要说了:你这家伙,创建人家的时候是不是干了什么事情
我们往上看看命令
哦,原来罪魁祸首是这个--rm
参数,他让容器运行结束后自动删除了(这样做的好处是,减少exit状态容器的出现)
docker build
:通过Dockerfile 构建镜像
docker build -t <镜像名称[:标签]> <上下文目录(dockerfile所在目录)>
# 标签缺省则默认为latest
我们现在已经有一个dockerfile文件了,存放在./Dockerfile目录下
docker build -t nginx_test_dockerfile ./Dockerfile_task/
看看有咩有多一个叫nginx_test_dockerfile的镜像
docker images