个人学习笔记,谢绝转载!!!
原文:https://www.cnblogs.com/wshenjin/p/9323013.html
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
因为镜像包含操作系统完整的 root
文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。
查看本地镜像
docker images :
[root@docker-machine_192.168.31.129 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos latest 88ec626ba223 5 weeks ago 199.7 MB
centos 7 88ec626ba223 5 weeks ago 199.7 MB
各项目说明:
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签,默认latest
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- VIRTUAL SIZE:镜像大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如ubuntu仓库源里,有15.10、14.04等多个不同的版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。例如,运行一个centos7容器:
[root@docker-machine_192.168.31.129 ~]# docker run -t -i centos:7 /bin/bash
[root@eb92e9fee2c6 /]#
如上,如果不指定TAG,则默认使用latest。
搜索镜像
docker search:
[root@docker-machine_192.168.31.129 ~]# docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 9029 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker c... 1361 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable ... 589 [OK]
jrcs/letsencrypt-nginx-proxy-companion LetsEncrypt container to use with nginx as... 390 [OK]
kong Open-source Microservice & API Management ... 204 [OK]
webdevops/php-nginx Nginx with PHP-FPM 106 [OK]
各项目说明:
NAME:镜像仓库源的名称
DESCRIPTION:镜像的描述
OFFICIAL:是否docker官方发布
获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]:
-
Docker 镜像仓库地址:地址的格式一般是
<域名/IP>[:端口号]
。默认地址是 Docker Hub。 -
仓库名:仓库名是两段式名称,即
<用户名>/<软件名>
。对于 Docker Hub,如果不给出用户名,则默认为library
,也就是官方镜像。例如:
[root@docker-machine_192.168.31.129 ~]# docker pull training/webapp
latest: Pulling from training/webapp
e9e06b06e14c: Downloading [======> ] 8.256 MB/65.77 MB
e9e06b06e14c: Download complete
a82efea989f9: Download complete
37bea4ee0c81: Download complete
07f8e8c5e660: Download complete
23f0158a1fbe: Download complete
0a4852b23749: Download complete
7d0ff9745632: Download complete
99b0d955e85d: Download complete
33e109f2ff13: Download complete
cc06fd877d54: Download complete
b1ae241d644a: Download complete
b37deb56df95: Download complete
02a8815912ca: Download complete
Status: Downloaded newer image for training/webapp:latest
提交镜像
docker commit
如果没有满足我们需要的镜像时,我们可以自己制作镜像,也可以从已有的镜像中更新提交一个合适自己的镜像
更新镜像之前,先用centos7创建一个容器:
[root@docker-machine_192.168.31.129 ~]# docker run -t -i centos:7 /bin/bash
[root@eb92e9fee2c6 /]#
这时,我们已经进入了容器了
我们在容器内执行我们需要的操作,例如,新建一个admin用户:
[root@ba03649e5f96 /]# id admin
id: admin: no such user
[root@ba03649e5f96 /]# useradd admin
[root@ba03649e5f96 /]# id admin
uid=1000(admin) gid=1000(admin) groups=1000(admin)
退出容器,用docker commit进行提交:
[root@docker-machine_192.168.31.129 ~]# docker commit -m="with a user named admin" -a="root" ba03649e5f96 centos:v7.1
461de5c9b34eb31ef35047fff8038342a658ab1808ecf568904401570b84ce35
各项目说明:
-
-m:提交的描述信息
-
-a:指定镜像作者
-
ba03649e5f96:容器ID
-
centos:v7.1:指定要创建的目标镜像名
查看一下本地镜像:
[root@docker-machine_192.168.31.129 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos v7.1 461de5c9b34e 10 minutes ago 200 MB
centos 7 88ec626ba223 6 weeks ago 199.7 MB
centos latest 88ec626ba223 6 weeks ago 199.7 MB
training/webapp latest 02a8815912ca 3 years ago 348.8 MB
使用新提交的镜像运行容器:
[root@docker-machine_192.168.31.129 ~]# docker run -t -i centos:v7.1 /bin/bash
[root@7b4e7cd30e88 /]# id admin
uid=1000(admin) gid=1000(admin) groups=1000(admin)
构建镜像
docker build
使用命令 docker build , 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像
找个空目录,新建一个Dockerfile 文件,我们让新建的镜像拥有admin用户:
FROM centos
RUN useradd admin
CMD ["/bin/bash"]
Dockerfile 文件的命令及其具体含义这里先不解析
使用命令 docker build 来创建我们想要的镜像:
[root@docker-machine_192.168.31.129 docker]# ll
total 4
-rw-r--r-- 1 root root 49 Jul 17 19:28 Dockerfile
[root@docker-machine_192.168.31.129 docker]# docker build -t centos:v1 .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM centos
---> 88ec626ba223
Step 1 : RUN useradd admin
---> Running in a85096739c0f
---> c1020ec616a9
Removing intermediate container a85096739c0f
Step 2 : CMD /bin/bash
---> Running in 4fb1f7b019aa
---> f24c4c696e23
Removing intermediate container 4fb1f7b019aa
Successfully built f24c4c696e23
[root@docker-machine_192.168.31.129 docker]#
命令末尾的 . 指明 build context 为当前目录。Docker 默认会从 build context 中查找 Dockerfile 文件,我们也可以通过 -f 参数指定 Dockerfile 的位置
上面的流程为:
- 从ID为88ec626ba223的centos 作为base镜像
- 执行RUN,添加admin用户
- 执行CMD
- 保存到镜像ID为f24c4c696e23
从上面的输出可以看出,从base镜像之后的每一步其实都是保存到临时容器中的,最后保存的镜像ID就是:Successfully built f24c4c696e23
让我们来看看本地的镜像:
[root@docker-machine_192.168.31.129 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos v1 f24c4c696e23 6 minutes ago 200 MB
hello-world latest 3535063d9957 6 days ago 1.848 kB
centos 7 88ec626ba223 6 weeks ago 199.7 MB
centos latest 88ec626ba223 6 weeks ago 199.7 MB
training/webapp latest 02a8815912ca 3 years ago 348.8 MB
用新建的镜像来启动一个容器:
[root@docker-machine_192.168.31.129 docker]# docker run -i -t --rm centos:v1
[root@a52b97b4aac8 /]# id admin
uid=1000(admin) gid=1000(admin) groups=1000(admin)
[root@a52b97b4aac8 /]# exit
exit
[root@docker-machine_192.168.31.129 docker]#
新构建的镜像中有了admin用户了,这里docker run命令后面跟上--rm参数是为了使这个容器为临时容器,退出时自动被删除
在centos:v1的基础上再构建一个新镜像:
FROM centos:v1
RUN groupadd www
RUN useradd -g www,admin -s /sbin/nologin www
CMD ["/bin/bash"]
[root@docker-machine_192.168.31.129 docker]# docker build -t centos:v2 .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM centos:v1
---> f24c4c696e23
Step 1 : RUN groupadd www
---> Using cache
---> db90442b2ffb
Step 2 : RUN useradd -g www -s /sbin/nologin www
---> Running in a006bee63c63
---> c7c01f1b0dd2
Removing intermediate container a006bee63c63
Step 3 : CMD /bin/bash
---> Running in 37a9e708bd9a
---> ecf3512fa6e6
Removing intermediate container 37a9e708bd9a
Successfully built ecf3512fa6e6
[root@docker-machine_192.168.31.129 docker]#
从上面的构建流程来看,centos:v2是在centos:v1的基础上进行构建的。这就是docker镜像的分层结构,具体这里先不说。
我们用history命令来查看一下centos:v2的构建过程:
[root@docker-machine_192.168.31.129 docker]# docker history centos:v2
IMAGE CREATED CREATED BY SIZE COMMENT
ecf3512fa6e6 2 minutes ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
c7c01f1b0dd2 2 minutes ago /bin/sh -c useradd -g www -s /sbin/nologin ww 295.3 kB
db90442b2ffb 2 minutes ago /bin/sh -c groupadd www 1.34 kB
f24c4c696e23 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
c1020ec616a9 15 minutes ago /bin/sh -c useradd admin 296.2 kB
88ec626ba223 6 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
b298d692482d 6 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sch 0 B
29466d114cd8 6 weeks ago /bin/sh -c #(nop) ADD file:8f4b3be0c1427b158f 199.7 MB
从上面可以看出,centos:v2是在centos:v1的上面进行构建的
删除镜像
dockr rmi
删除镜像前,必须先删除由该镜像创建的容器,哪怕该容器没在运行,如下:
[root@docker-machine_192.168.31.129 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b43371be7bd centos:v2 "/bin/bash" About a minute ago Up About a minute ecstatic_wilson
[root@docker-machine_192.168.31.129 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos v2 ecf3512fa6e6 7 minutes ago 200.3 MB
centos v1 f24c4c696e23 19 minutes ago 200 MB
hello-world latest 3535063d9957 6 days ago 1.848 kB
centos 7 88ec626ba223 6 weeks ago 199.7 MB
centos latest 88ec626ba223 6 weeks ago 199.7 MB
training/webapp latest 02a8815912ca 3 years ago 348.8 MB
[root@docker-machine_192.168.31.129 docker]# docker rmi ecf3512fa6e6
Error response from daemon: Conflict, cannot delete ecf3512fa6e6 because the running container 4b43371be7bd is using it, stop it and use -f to force
Error: failed to remove images: [ecf3512fa6e6]
[root@docker-machine_192.168.31.129 docker]# docker stop 4b43371be7bd
4b43371be7bd
[root@docker-machine_192.168.31.129 docker]# docker rmi ecf3512fa6e6
Error response from daemon: Conflict, cannot delete ecf3512fa6e6 because the container 4b43371be7bd is using it, use -f to force
Error: failed to remove images: [ecf3512fa6e6]
[root@docker-machine_192.168.31.129 docker]# docker rm 4b43371be7bd
4b43371be7bd
[root@docker-machine_192.168.31.129 docker]# docker rmi ecf3512fa6e6
Untagged: centos:v2
Deleted: ecf3512fa6e6f5bfbea3937f6cc4849bf7c5597b4f57365cab67e1359457a5f9
Deleted: c7c01f1b0dd2309613a3430d826bd5be9bbab1d5ccc978b2ecbb86e93600c2b0
Deleted: db90442b2ffbf4b9025cd21cf0f58dba147e71de0c5153d9903d10ad0970b926
[root@docker-machine_192.168.31.129 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos v1 f24c4c696e23 20 minutes ago 200 MB
hello-world latest 3535063d9957 6 days ago 1.848 kB
centos 7 88ec626ba223 6 weeks ago 199.7 MB
centos latest 88ec626ba223 6 weeks ago 199.7 MB
training/webapp latest 02a8815912ca 3 years ago 348.8 MB
删除镜像:docker rmi [img_name|img_id]
删除容器:docker rm [container _name|container _id]
不过,容器都停止的情况下,docker rmi可以加个-f参数强制删除。不过没有傻缺会这么做,结果很明显:停止的容器都会起不来的