文章目录
Docker
有三大基本概念
- 镜像 image
- 容器 container
- 仓库 repository
学习 Docker
,理解这三大概念就理解了 Docker
的整个生命周期。
1. 镜像 - image
Docker
镜像是一个文件系统,其包含了容器运行所需的所有文件,还包含一些配置数据,是容器能够正常运行的基础。镜像是静态的,它在构建完成之后就不会再改变。(后文描述时使用镜像代替 Doker
镜像)
镜像采用分层存储的架构设计,镜像是一个虚拟的概念,其实体有多层文件系统联合构成。
镜像构建时,分层构建,后层依赖前层,每一层构建完成后不再改变,后层的任务改动只影响本层,这就要求我们构建时以 最小化
为原则只构建本层需要的东西,还有就是,可以在构建完成之前删除已完成的需求。
反之,不以最小化原则构建的镜像会越来越臃肿,运行缓慢,效率低
1.1 拉取镜像
拉取镜像的命令是 docker pull name:tag
,就像下边这样:
docker command --help
可以查看任何 docker
命令的帮助文件,只要不清楚docker
命令如何使用,都可以这么查。
1.2 运行镜像
有了镜像,就可以运行容器了,下面是个示例:
docker run -it --rm ubuntu:18.04 bash
cat /etc/os-release
命令解释
docker run
:运行容器的指令
-it
:是两个参数,-i
是交互式,-t
是终端`
--rm
:容器退出后马上删除
ubuntu:18.04
:镜像
bash
:运行的命令
exit
:退出
1.3 查看镜像
查看顶层镜像:docker image ls
查看所有镜像:docker image ls -a
查看镜像、容器、数据卷占用的空间大小:docker system df
仓库和标签均为 none
的镜像称为 虚悬镜像 (dangling image)
,它是由于新旧镜像同名,旧镜像名和标签被取消而造成的,docker pull / docker build
都可能导致此现象。
查看所有虚悬镜像:docker image ls -f dangling=true
删除所有虚悬镜像:docker image prune
列出特定应用的镜像:docker image ls nginx
列出特定应用特定版本的镜像:docker image ls ubuntu:18.04
查看特定应用之前或之后建立的镜像:
docker image ls -f before=mongo:3.2
docker image ls -f since=mongo:3.2
1.4 删除镜像
删除单个镜像:docker image rm xxx
删除某个应用的所有镜像:docker image rm $(docker image ls -q redis)
你可以充分运用 Linux
命令的优雅来达到预期的效果。
1.5 镜像构建举例
运行命令:docker run --name webserver -d -p 80:80 nginx
该命令会用 nginx
镜像启动一个容器,命名为 webserver
,并且映射了 80
端口,这样我们可以用浏览器去访问这个 nginx
服务器。
此时本地浏览器访问 http://localhost
即可看到如下页面:
我们还可以使用
docker exec
命令进入容器,修改它的内容,详见下图:
刷新刚才的浏览器页面,即可看到如下内容:
docker diff webserver
命令可以看到具体的改动
假设我们现在想把这个改动后的镜像保存下来,该怎么办呢?
容器运行时,任何改动都会存储到容器存储层,而 docker commit
可以把容器存储层固化为镜像。
## Linux 命令
docker commit \
--author "ZhY Wang <mba1398@gmail.com>" \
--message "修改了默认网页" \
webserver \
nginx:v2
## powershell 命令,powershell 中,换行符是1左边那个键:`
docker commit `
--author "ZhY Wang <mba1398@gmail.com>" `
--message "修改了默认网页" `
webserver `
nginx:v22
这里,--author
指定了作者,--message
描述了本次修改的信息,
我们可以运行此镜像:docker run --name web2 -d -p 81:80 nginx:v22
,
访问 http://localhost:81
可以看到如下结果,其内容和 webserver
修改后的内容一致。
至此,我们完成了第一个定制的镜像。
值得注意的是,docker commit
制作的镜像称为 黑箱镜像
,因为别人无从知晓镜像的内容,制作人也非常容易忘记当初自己的制作过程,所以说此方法是不推荐使用的。
还有就是,docker commit
方法制作的镜像容易越来越臃肿。
1.6 使用 Dockerfile 定制镜像
前面提到了 docker commit
制作镜像的各种缺点,那是否存在更好的方法呢?答案是肯定的。dockerfile
就是一种解决方案,其本质是一个批处理脚本,包含了多条指定集,用来构建不同的层。
注意: dockerfile
最好在空目录创建。
它主要有 FROM
和 RUN
两部分构成。其中,FROM
指定了基础镜像,RUN
包含了用来实现各项定制化需求的指令。
在 dockerfile
文件所在目录执行如下命令完成构建:
docker build -t nginx:v3 .
可以看到,我们成功了构建了
nginx:v3
镜像,它可以像 nginx:v2
那样运行: docker run --name web3 -d -p 82:80 nginx:v3
,访问 http://localhost:82
即可看到如下结果:
其他构建方法可以参考网址:https://vuepress.mirror.docker-practice.com/image/other/
2. 容器 - container
容器就是依托镜像而运行的实体,它可以被创建、启动、停止、删除、暂停等。
其本质是进程,而不与宿主进程发生冲突,因为其 命名空间
是独立的。
容器消亡时,数据也会被删除,所以,不应向容器存储层存储数据,应使用数据卷等技术对宿主机进行读写操作,后续再学习这一块的内容。
2.1 新建并启动容器
容器有如下两种启动方式:
- 基于镜像新建一个容器并启动;
- 将在终止状态(
exited
)的容器重新启动;
新建并启动容器的命令是 docker run
。
下面的命令输出 Hello Datawhale Learner
之后便终止容器。
docker run ubuntu:18.04 /bin/echo 'Hello Datawhale Learner'
Hello Datawhale Learner
下面的命令则启动一个 bash
终端,允许用户进行交互操作,这里的交互操作和 Linux
系统完全一致
asd@CC:/mnt/e/mynginx$ docker run -t -i ubuntu:18.04 /bin/bash
root@2c6521e3b598:/# pwd
/
root@2c6521e3b598:/# ll
total 72
drwxr-xr-x 1 root root 4096 Apr 13 15:29 ./
drwxr-xr-x 1 root root 4096 Apr 13 15:29 ../
-rwxr-xr-x 1 root root 0 Apr 13 15:29 .dockerenv*
drwxr-xr-x 2 root root 4096 Mar 25 16:45 bin/
drwxr-xr-x 2 root root 4096 Apr 24 2018 boot/
drwxr-xr-x 5 root root 360 Apr 13 15:29 dev/
drwxr-xr-x 1 root root 4096 Apr 13 15:29 etc/
drwxr-xr-x 2 root root 4096 Apr 24 2018 home/
drwxr-xr-x 8 root root 4096 May 23 2017 lib/
drwxr-xr-x 2 root root 4096 Mar 25 16:45 lib64/
drwxr-xr-x 2 root root 4096 Mar 25 16:44 media/
drwxr-xr-x 2 root root 4096 Mar 25 16:44 mnt/
drwxr-xr-x 2 root root 4096 Mar 25 16:44 opt/
dr-xr-xr-x 167 root root 0 Apr 13 15:29 proc/
drwx------ 2 root root 4096 Mar 25 16:45 root/
drwxr-xr-x 1 root root 4096 Mar 25 22:33 run/
drwxr-xr-x 1 root root 4096 Mar 25 22:32 sbin/
drwxr-xr-x 2 root root 4096 Mar 25 16:44 srv/
dr-xr-xr-x 11 root root 0 Apr 13 15:29 sys/
drwxrwxrwt 2 root root 4096 Mar 25 16:45 tmp/
drwxr-xr-x 1 root root 4096 Mar 25 16:44 usr/
drwxr-xr-x 1 root root 4096 Mar 25 16:45 var/
root@2c6521e3b598:/#
其中,-t
选项让 Docker
分配一个伪终端( pseudo-tty
)并绑定到容器的标准输入上, -i
则让容器的标准输入保持打开。
执行 docker run
命令创建容器时,`Docker 后台的标准动作如下:
- 检查本地是否存在指定的镜像,不存在就从
注册仓库
下载 - 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
2.2 启动已经终止的容器
使用 docker start containerId/containerName
命令可以启动已经终止( exited
)的容器,那么如何知道已经终止的容器是哪些呢?
实际上,docker ps
指令仅列出正在运行的容器,而 docker ps -a
指令列出所有容器,包括已经终止的,详见下图:
如下图所示,使用
docker start romantic_rosalind
命令重新启动了已经终止的容器 romantic_rosalind
使用
docker container start containerId/containerName
命令也可以启动已停止的容器。
2.3 停止容器
如下两个命令都可以停止容器
docker stop containerId/containerName
docker container stop containerId/containerName
详见下图:
2.4 后台运行容器
有时候我们容器将打印结果输出到宿主机屏幕,此时就需要容器在后台运行,-d
参数可以实现此需求:
对比如上两条命令可以看出,不加
-d
参数时,宿主机直接打印输出结果,加上 -d
参数时,返回 containerId(完整ID)
,使用 docker logs containerId
可以参考打印输出。
也可以使用
docker container ls -a
命令查找出当前最新的容器,然后用短ID查询。
2.5 进入容器
有时需要进入容器进行操作,docker attach
或 docker exec
命令都可以使用,推荐大家使用 docker exec
命令,原因是:使用 docker attach
进入容器后,输入 exit
将会导致容器停止。
docker exec
命令不存在此问题:
这里需要说明的是:
docker exec
后边可以添加多个参数,单独使用 -i
参数时,终端有返回输出但是没有 Linux
命令提示符,-it
参数一起使用时,则可以看到 Linux
提示符。
2.6 导入和导出容器
-
快照导入
-
URL 或者目录导入
docker import http://example.com/exampleimage.tgz example/imagerepo
2.7 删除容器
处理终止状态的容器才能删除,计划删除容器时,可以先终止容器也可以在删除命令 docker container rm containerID/containName
中添加 -f
参数,该参数触发 docker
发送 SIGKILL
命令给容器,进而杀死容器。
docker container prune
可以批量清理所有处于终止状态的容器,务必谨慎使用
3. 仓库 - repository
镜像构建完成后,如果想在其他服务器上进行移植,就需要一个集成的存储、分发镜像的服务,这个服务就是 Docker repository
(仓库)。
一个 Docker Registry
中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。
不同版本的镜像用 <name>:<tag>
标识,举个栗子:ubuntu:18.04
。
Docker Registry
有公共的也有私有的。公共的就是大厂提供的免费服务,私有的就是收费的或者个人的仓库。