Docker--镜像的创建

本文介绍了Docker构建镜像的两种方式,即docker commit和Dockerfile。docker commit效率低、有安全隐患;Dockerfile可自动构建,能让使用者对镜像进行审计。还详细介绍了Dockerfile的常用指令,如FROM、COPY等,以及数据卷挂载、命令执行模式等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

构建镜像的两种方式

docker commit :将运行的容器保存成镜像
Dockerfile:自动构建

docker commit

使用docker commit 创建镜像分为三步:

  • 运行容器
  • 修改容器
  • 将容器保存为镜像

特点:
效率低、可重复性弱、容易出错
使用者无法对镜像进行审计(看不到镜像中的操作),会存在安全隐患

以镜像busybox为例进行说明:

  • 运行容器:
[root@toto6 images]# docker run -it --name test busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
  • 修改容器:
/ # echo "hello toto" > testfile
/ # ls
bin       etc       proc      sys       tmp       var
dev       home      root      testfile  usr
  • 将容器保存为新的镜像:
[root@toto6 images]# docker commit test busybox:v2
sha256:0cdf20286e297b35345970340031e9ec0ad49128f790e82ec348f22470c8cd0e
  • 查看新生成的镜像:无法看新镜像层的操作
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
0cdf20286e29        About a minute ago   sh                                              46B                 
59788edf1f3e        9 months ago         /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           9 months ago         /bin/sh -c #(nop) ADD file:63eebd629a5f7558c…   1.15MB              

直接运行新生成的镜像容器:

[root@toto6 images]# docker run -it --name test busybox:v2 
/ # ls
bin       etc       proc      sys       tmp       var
dev       home      root      testfile  usr   # 里面保存了之前操作的数据。
Dockerfile 创建镜像

根据Dockerfile中的内容,通过使用docker bulid指令,自动创建镜像,也是基于docker commit的层层构建得出。

Dockerfile文件名称,是docker默认的,在u不特殊指定的情况下,一般都是从该文件中读取创建信息。并且在创建的过程中,docker会将该文件所在目录中的所有内容发送给docker引擎。所以建创建一个空来目录来存放Dockerfile文件。

使用Dockerfile创建镜像

查看已经存在的镜像

[root@toto6 images]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              59788edf1f3e        9 months ago        1.15MB
game2048            latest              19299002fdbe        2 years ago         55.5MB
ubuntu              latest              07c86167cdc4        3 years ago         188MB
rhel7               latest              0a3eb3fde7fd        5 years ago         140MB

创建空目录以及Dockerfile文件

[root@toto6 images]# mkdir /docker
[root@toto6 images]# cd /docker/
[root@toto6 docker]# vim Dockerfile
FROM busybox    # 以已经存在的busybox进行为base镜像
RUN echo 'hello world'   # 新加的操作,每一个RUN产生一个新的镜像层
RUN echo 'westos linux'

创建新的镜像:. 表示Dockerfile所在的路径

[root@toto6 docker]# docker build -t busybox:v2 .
Sending build context to Docker daemon  2.048kB    # 将目录中的所有内容发送给docker引擎
Step 1/3 : FROM busybox    #第一层
 ---> 59788edf1f3e
Step 2/3 : RUN echo 'hello world'   # 第二层
 ---> Running in 9e201f6f8641
hello world
Removing intermediate container 9e201f6f8641
 ---> 4dc2056e315e
Step 3/3 : RUN echo 'westos linux'   # 第三层
 ---> Running in d957a3a99acf
westos linux
Removing intermediate container d957a3a99acf
 ---> 8fed8fc9f3f2
Successfully built 8fed8fc9f3f2
Successfully tagged busybox:v2   # 创建成功

成功之后再次查看镜像,已经成功生成镜像

[root@toto6 docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             v2                  8fed8fc9f3f2        59 seconds ago      1.15MB
busybox             latest              59788edf1f3e        9 months ago        1.15MB
game2048            latest              19299002fdbe        2 years ago         55.5MB
ubuntu              latest              07c86167cdc4        3 years ago         188MB
rhel7               latest              0a3eb3fde7fd        5 years ago         140MB

查看新生成的镜像分层结构:
能清楚的看到每一层镜像进行的操作,使用者可以对镜像进行审计

[root@toto6 docker]# docker history busybox:v2 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
8fed8fc9f3f2        9 minutes ago       /bin/sh -c echo 'westos linux'                  0B                  
4dc2056e315e        9 minutes ago       /bin/sh -c echo 'hello world'                   0B                  
59788edf1f3e        9 months ago        /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           9 months ago        /bin/sh -c #(nop) ADD file:63eebd629a5f7558c…   1.15MB              

当不修改刚才的Dockerfile的基础上再次添加内容创建镜像的时候

[root@toto6 docker]# vim Dockerfile 
FROM busybox
RUN echo 'hello world'
RUN echo 'westos linux'
RUN echo toto > totofile    # 添加一条新的语句

再上一次的基础上构建新的镜像

[root@toto6 docker]# docker build  -t busybox:v3 .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM busybox
 ---> 59788edf1f3e
Step 2/4 : RUN echo 'hello world'
 ---> Using cache     # 和上一次一致,使用存在的cache
 ---> 4dc2056e315e
Step 3/4 : RUN echo 'westos linux'
 ---> Using cache   # 和上一次一致,使用存在的cache
 ---> 8fed8fc9f3f2
Step 4/4 : RUN echo toto > totofile
 ---> Running in d611a8f1892c    # 打开一个新的容器运行新加的操作
Removing intermediate container d611a8f1892c   # 运行完成之后释放自己新建的容器
 ---> 41b1abbffebf    #提交新建的镜像层
Successfully built 41b1abbffebf
Successfully tagged busybox:v3   # 镜像创建成功

查看新生成的镜像分层结构:
在Dockerfile文件中,每一个RUN语句都会生成一个新的镜像层。

[root@toto6 docker]# docker history busybox:v3
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
41b1abbffebf        4 minutes ago       /bin/sh -c echo toto > totofile                 5B                  
8fed8fc9f3f2        31 minutes ago      /bin/sh -c echo 'westos linux'                  0B                  
4dc2056e315e        31 minutes ago      /bin/sh -c echo 'hello world'                   0B                  
59788edf1f3e        9 months ago        /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           9 months ago        /bin/sh -c #(nop) ADD file:63eebd629a5f7558c…   1.15MB              
Dockerfile的详细介绍
dickerfile 常用指令:

1 、FROM:
用于指定base镜像,本地不存在会从远程仓库进行下载

2、MAINTAINER
MAINTAINER:设置镜像的作者,如用户邮箱等(不是必须的)

3、COPY
把文件从build context复制到镜像
支持两种形式:COPY src dest和COPY [" src" ,"dest "]
src必须指定build context中的文件或目录
dest为容器中的路径

[root@toto6 docker]# vim Dockerfile 
		FROM busybox
		CPOY Dockerfile  /mnt
[root@toto6 docker]# docker run -it --name vm1 test:v1 
/ # ls
bin   dev   etc   home  mnt   proc  root  sys   tmp   usr   var

4 、ADD

用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可自动下载URL并拷贝到镜像
DD html.tar /var/www ##解压
ADD http://ip/html.tar /var/www ##下载

[root@toto6 docker]# ls
backup.tar.gz  Dockerfile
[root@toto6 docker]# vim Dockerfile 
FROM rhel7
Add backup.tar.gz  /mnt
[root@toto6 docker]# docker build -t test:v3 .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM rhel7
 ---> 0a3eb3fde7fd
Step 2/2 : Add backup.tar.gz  /mnt
 ---> d8b34bccc29a
Successfully built d8b34bccc29a
Successfully tagged test:v3
[root@toto6 docker]# docker run -it --name vm3 test:v3
docker: Error response from daemon: No command specified.
See 'docker run --help'.
[root@toto6 docker]# docker run -it --name vm3 test:v3 bash
bash-4.2# ls /mnt
usr

5 EXPOSE
如果容器中运行应用服务,则可以包服务端口暴露出去

[root@toto6 docker]# vim Dockerfile 
FROM rhel7
Add backup.tar.gz  /mnt
EXPOSE 80

[root@toto6 docker]# docker history test:v4
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
125f2a6e4982        10 seconds ago      /bin/sh -c #(nop)  EXPOSE 80                    0B                  
d8b34bccc29a        4 minutes ago       /bin/sh -c #(nop) ADD file:a6708d65f40d03475…   0B                  
0a3eb3fde7fd        5 years ago                                                         140MB               Imported from -

6 、VOLUME
声明数据卷,通常指定应用数据挂载点
VOLUME [ “/var/www/html”] :该路径为容器中的路径。如果路径不存在,启动容器的时候会自动创建

  • 一般VOLUME指定挂载点,没有此路径就会新建路径。
  • 在运行docker宿主机上,可以根据命令docker inspect 容器名的具体信息,可以查看封装容器,声明的数据卷,Source会存在此容器目录挂接到本地_data目录。
  • 由于自动挂载的路径很长,不太方便记,也可以在运行的时候指定挂载路径
[root@toto6 docker]# vim Dockerfile
FROM rhel7
EXPOSE 80
VOLUME ["/data"]    # 声明数据卷
[root@toto6 docker]# docker build -t test:v1 .
[root@toto6 docker]# docker run -it --name vm2 test:v1  bash
bash-4.2# ls
bin   data  etc   lib	 media	opt   root  sbin  sys  usr
boot  dev   home  lib64  mnt	proc  run   srv   tmp  var    # 容器中生成了data目录

#使用ctrl + pq 保证容器正常运行退出交互式界面。

[root@toto6 docker]# docker inspect vm2  # 查看运行容器的信息
"Mounts": [
            {
                "Type": "volume",
                "Name": "280eb155e5ef61cfaf300b8d597f057005cc66fb9af39361b9f1b4e53d5ca2a0",
                "Source": "/var/lib/docker/volumes/280eb155e5ef61cfaf300b8d597f057005cc66fb9af39361b9f1b4e53d5ca2a0/_data",
# Source为容器中声明的数据卷在宿主机上的挂载路径。

在宿主机上在该挂载目录中创建文件,可以在容器中相应的目录中看到:

[root@toto6 docker]# cd /var/lib/docker/volumes/280eb155e5ef61cfaf300b8d597f057005cc66fb9af39361b9f1b4e53d5ca2a0/_data
[root@toto6 _data]# ls
[root@toto6 _data]# touch file1
[root@toto6 _data]# ls
file1
#再次连接容器:
[root@toto6 _data]# docker attach vm2 
bash-4.2# ls /data
file1
上面声明数据卷,并没有指定在宿主机上的挂载点。该挂载点由docker自动分配。还可以自己指定数据卷的挂载。
docker run -it --name vm3 -v /opt/data:/data test:v1    ##:前为物理机挂载目录,:后为docker挂载目录

7 、WORKDIR
为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在也会自动创建

8 、RUN
RUN 在容器中运行命令并创建新的镜像层,常用于安装软件包:每个run 都会多一层

9 、ENV:
设置环境变量,变量可以被后续的指令使用

10 、CMD 与 ENTRYPOINT

设置容器启动后执行的命令,但是CMD会被docker run 后面的命令覆盖,但ENTRYPOINT不会
Dockerfile中只能指定一个ENTRYPOINT,如果指定过多则只有最后一个有效
docke run后面的参数可以传递给ENTRYPOINT指令当作参数;

shell模式:

[root@toto6 docker]# vim Dockerfile  
FROM busybox
ENV name toto   # 定义变量
ENTRYPOINT echo "hello,$name"    # 设置输出(shell命令行)

[root@toto6 docker]# docker build -t test:v2 .   # 创建镜像

[root@toto6 docker]# docker run --rm test:v2   # 运行容器
hello,toto   # 直接输出,同时对变量进行解析

exec模式

[root@toto6 docker]# vim Dockerfile  
FROM busybox
ENV name toto
ENTRYPOINT ["/bin/echo","hello,$name"]

[root@toto6 docker]# docker build -t test:v3 .   # 创建镜像

[root@toto6 docker]# docker run --rm test:v3   # 运行容器
hello,$name     # 输出并没有进行变量解析
原因:

这是由于shell格式底层会调用/bin/sh -C执行命令,可以解析变量。但是exec模式不会,

[root@toto6 docker]# docker history test:v2
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
b7801a7de9d6        7 minutes ago       /bin/sh -c #(nop)  ENTRYPOINT ["/bin/sh" "-c…   0B                  
c3ee45017cfb        7 minutes ago       /bin/sh -c #(nop)  ENV name=toto                0B                  
59788edf1f3e        9 months ago        /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           9 months ago        /bin/sh -c #(nop) ADD file:63eebd629a5f7558c…   1.15MB              
[root@toto6 docker]# docker history test:v3
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
57b3bcebd5b4        2 minutes ago       /bin/sh -c #(nop)  ENTRYPOINT ["/bin/echo" "…   0B                  
c3ee45017cfb        7 minutes ago       /bin/sh -c #(nop)  ENV name=toto                0B                  
59788edf1f3e        9 months ago        /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           9 months ago        /bin/sh -c #(nop) ADD file:63eebd629a5f7558c…   1.15MB              
处理办法:

所以只要指定/bin/sh -C指令解析命令。如下:

[root@toto6 docker]# vim Dockerfile
FROM busybox
ENV name toto
ENTRYPOINT ["/bin/sh","-c","echo hello,$name"]

[root@toto6 docker]# docker build -t test:v4 .

[root@toto6 docker]# docker run --rm test:v4
hello,toto

Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换,在shell格式时ENTRYPOINT会忽略任何CMD和docker run 提供的参数

[root@toto6 docker]# docker run --rm test:v2 lala   # shell 模式
hello,toto
[root@toto6 docker]# docker run --rm test:v3 lala   # exec模式
hello,$name lala

CMD命令在前,会被docker run后存在参数会被覆盖

[root@toto6 docker]# vim Dockerfile 
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["WORLD"]

[root@toto6 docker]# docker build -t test:v5 .  # 创建镜像

[root@toto6 docker]# docker run --rm test:v5   # 运行容器
hello WORLD

[root@toto6 docker]# docker run --rm test:v5  toto   # 运行容器 后面加参数
hello toto   # 显示CMD 指令被后面的参数覆盖
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值