Dockerfile

本文最后更新于 2025年1月8日

Dockerfile概述

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

从应用软件的角度来看,Dockerfile,Docker镜像,Docker容器分别代表软件的三个不同阶段

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器可以认为是软件的运行态

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及运维和部署,合力充当Docker体系的基石。

Dockerfile定义了进程需要的一切东西,Dockerfile涉及的内容包括执行代码或者文件,环境变量,依赖包,运行时环境,动态链接库,操作系统发行版,服务进程和内核进程(当应用程序需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等。

Docker镜像,在用Dockerfile定义了一个构建文件之后,docker build时会产生一个Docker镜像,当运行Docker镜像时,会开始真正的提供服务。

Docker容器,是直接提供服务的进程。

Dockerfile构建过程:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令,并对容器进行修改
  3. 执行类似docker commit的操作,提交一个新的镜像层
  4. docker再基于刚刚提交的镜像运行一个新容器
  5. 继续执行Dockerfile的下一条指令,直到所有指令都执行完成

Dockerfile的保留字指令

Dockerfile每个保留字指令均为大写,且后面至少跟随一个参数,指令从上到下顺序执行,用#表示注释。

  • FROM

    基本出现在第一行,意思是要构建的新镜像继承于或者说基于哪个已存在的镜像。

    FROM ubuntu:20.04
  • MAINTAINR

    维护者信息(姓名和邮箱地址)

  • ENV

    用于在构建镜像的过程中设置环境变量,这个环境变量可以在后续的任何RUN指令中使用,就像在命令前面指定了环境变量一样,也可以在其他指令中直接使用这些环境变量,比如WORKDIR $JAVA_HOME

    ENV PATH="/usr/local/bin:${PATH}"
  • RUN

    容器构建(docker build)时需要运行的命令,分为shellexec两种格式

    shell

    RUN apt-get update && apt-get install -y curl

    exec

    CMD ["可执行文件", "参数1", "参数2", ......]
  • EXPOSE

    声明容器运行时应该开放的端口。它不会自动开启端口,但为外部用户或其他容器提供信息

    EXPOSE 80 443
  • WORKDIR

    指定在创建容器后,终端默认登录进来的工作目录,当执行docker run -it 镜像ID /bash进入容器内部的时候,会默认落脚在哪个目录里

  • USER

    指定镜像以什么用户去执行,如果不指定,默认是root

    USER myuser
  • VOLUME

    容器数据卷,用于数据的保存和持久化,声明容器内的哪个目录需要在运行时挂载数据卷到宿主机上

    VOLUME ["/data"]
  • ADD

    ADD功能相比COPY更加强大,将宿主机内的文件拷贝进镜像,如果源文件是.tar.tar.gz等压缩格式的文件,ADD会自动解压到目标路径。ADD还可以从指定的URL下载文件并复制到容器内。

    ADD <宿主机源路径> <容器内目标路径>
  • COPY

    仅仅执行文件的复制,不支持自动解压或下载

    COPY <宿主机源路径> <容器内目标路径>
  • CMD

    指定容器启动后要做的事情,支持shellexec两种格式,还支持参数列表格式,如果指定了ENTRYPOINT指令,CMD就会被用来指定具体的运行参数

    注意事项

    1.RUNCMD的区别: RUN是构建镜像时执行,CMDdocker run容器启动时执行

    2.Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

    例如:tomcat的Dockerfile的最后一行是CMD ["catalina.sh", "run"],那么使用docker run -it tomcat /bin/bash命令启动这个镜像时,容器会启动,但是tomcat就不会被启动,因为被run后的命令/bin/bash替换掉了,故容器启动后会运行/bin/bash

  • ENTRYPOINT

    类似于CMD命令,但是不会被docker run后的命令覆盖,而且还会把docker run后的命令当作命令行参数传递给ENTRYPOINT指令指定的程序

    ENTRYPOINT ["可执行文件", "参数1", "参数2", ......]

    ENTRYPOINT可以和CMD一起用,一般是变参才会使用到CMD,这里的CMD等同于是在给ENTRYPOINT传参,当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,它们两个组合后会变成<ENTRYPOINT> "<CMD>"

    案例:

    FROM nginx
    
    ENTRYPOINT ["nginx", "-c"] #相当于命令加定参
    
    CMD ["/etc/nginx/nginx.conf"] #相当于可替换的变参
    按照Dockerfile原样执行 传参运行
    Docker命令 docker run nginx docker run nginx /etc/nginx/kms.conf
    容器实际执行 nginx -c /etc/nginx/nginx.conf nginx -c /etc/nginx/kms.conf

如果写成docker run nginx -c /etc/nginx/kms.conf也可以实现参数替换,-c不会被重复的叠加成docker run nginx -c -c /etc/nginx/kms.conf,因为ENTRYPOINT本身未包含-c,而CMD提供了-c的值

用Dockerfile构建镜像

  编写一个Dockerfile,用于构建一个自带Java17环境的RockyLinux9镜像,构建的镜像基于发行版rockylinux:8.9,新镜像内新增vimnet-tools组件,并将下载好的jdk17拷贝进去,并设置jdk相关的环境变量,让这个镜像构建的容器自带原版镜像不默认安装的一些工具,并且自带jdk17

找到一个空文件夹,vim Dockerfile编辑文件将构建命令写进去

FROM rockylinux:8.9

MAINTAINER lzj2023@foxmail.com

ENV MYPATH /opt

WORKDIR $MYPATH

RUN yum install -y vim net-tools 

RUN mkdir /opt/jdk

# 此处使用相对路径,jdk-17.0.12_linux-x64_bin.tar.gz要和Dockerfile在同一目录
ADD jdk-17.0.12_linux-x64_bin.tar.gz /opt/jdk

ENV JAVA_HOME /opt/jdk/jdk-17.0.12

ENV PATH $JAVA_HOME/bin:$PATH

CMD ["/bin/bash"]

编写完成后,再将要打包进去的jdk-17.0.12_linux-x64_bin.tar.gz放在同级目录,然后在这个目录内执行docker build命令,会用当前目录(.)下的Dockerfile构建镜像,镜像名称和标签是rockey8_jdk17:1.0.0

docker build -t rockey8_jdk17:1.0.0  .

执行输出

[root@localhost opt]# docker build -t rockey8_jdk17:1.0.0  .
Sending build context to Docker daemon  566.8MB
Step 1/11 : FROM rockylinux:8.9
8.9: Pulling from library/rockylinux
9088cdb84e39: Pull complete 
Digest: sha256:9794037624aaa6212aeada1d28861ef5e0a935adaf93e4ef79837119f2a2d04c
Status: Downloaded newer image for rockylinux:8.9
 ---> c79048e50f5f
Step 2/11 : MAINTAINER lzj2023@foxmail.com
 ---> Running in 9c40b7e878e1
Removing intermediate container 9c40b7e878e1
 ---> e58d03a7ebae
Step 3/11 : ENV MYPATH /opt
 ---> Running in d8448a9b4329
Removing intermediate container d8448a9b4329
 ---> da5da26abbe3
Step 4/11 : WORKDIR $MYPATH
 ---> Running in ddf20f025c3f
Removing intermediate container ddf20f025c3f
 ---> 2fe907e79d95
Step 5/11 : RUN yum -y install  vim
 ---> Running in f88378120cc1
Rocky Linux 8 - AppStream                       3.4 MB/s |  15 MB     00:04    
Rocky Linux 8 - BaseOS                          2.5 MB/s | 9.4 MB     00:03    
Rocky Linux 8 - Extras                          5.1 kB/s |  14 kB     00:02    
Dependencies resolved.
================================================================================
 Package            Arch       Version                      Repository     Size
================================================================================
Installing:
 vim-enhanced       x86_64     2:8.0.1763-19.el8_6.4        appstream     1.4 M
Installing dependencies:
 gpm-libs           x86_64     1.20.7-17.el8                appstream      38 k
 vim-common         x86_64     2:8.0.1763-19.el8_6.4        appstream     6.3 M
 vim-filesystem     noarch     2:8.0.1763-19.el8_6.4        appstream      49 k
 which              x86_64     2.21-20.el8                  baseos         49 k

Transaction Summary
================================================================================
Install  5 Packages

Total download size: 7.8 M
Installed size: 30 M
Downloading Packages:
[MIRROR] gpm-libs-1.20.7-17.el8.x86_64.rpm: Curl error (52): Server returned nothing (no headers, no data) for http://au.mirrors.cicku.me/rocky/8.10/AppStream/x86_64/os/Packages/g/gpm-libs-1.20.7-17.el8.x86_64.rpm [Empty reply from server]
[MIRROR] vim-common-8.0.1763-19.el8_6.4.x86_64.rpm: Curl error (52): Server returned nothing (no headers, no data) for http://au.mirrors.cicku.me/rocky/8.10/AppStream/x86_64/os/Packages/v/vim-common-8.0.1763-19.el8_6.4.x86_64.rpm [Empty reply from server]
[MIRROR] vim-enhanced-8.0.1763-19.el8_6.4.x86_64.rpm: Curl error (52): Server returned nothing (no headers, no data) for http://au.mirrors.cicku.me/rocky/8.10/AppStream/x86_64/os/Packages/v/vim-enhanced-8.0.1763-19.el8_6.4.x86_64.rpm [Empty reply from server]
(1/5): gpm-libs-1.20.7-17.el8.x86_64.rpm        4.6 kB/s |  38 kB     00:08    
(2/5): vim-filesystem-8.0.1763-19.el8_6.4.noarc 172 kB/s |  49 kB     00:00    
(3/5): vim-common-8.0.1763-19.el8_6.4.x86_64.rp 725 kB/s | 6.3 MB     00:08    
(4/5): vim-enhanced-8.0.1763-19.el8_6.4.x86_64. 144 kB/s | 1.4 MB     00:09    
[MIRROR] which-2.21-20.el8.x86_64.rpm: Curl error (52): Server returned nothing (no headers, no data) for http://au.mirrors.cicku.me/rocky/8.10/BaseOS/x86_64/os/Packages/w/which-2.21-20.el8.x86_64.rpm [Empty reply from server]
(5/5): which-2.21-20.el8.x86_64.rpm             7.4 kB/s |  49 kB     00:06    
--------------------------------------------------------------------------------
Total                                           449 kB/s | 7.8 MB     00:17     
Rocky Linux 8 - AppStream                       1.6 MB/s | 1.6 kB     00:00    
Importing GPG key 0x6D745A60:
 Userid     : "Release Engineering <infrastructure@rockylinux.org>"
 Fingerprint: 7051 C470 A929 F454 CEBE 37B7 15AF 5DAC 6D74 5A60
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                        1/1 
  Installing       : which-2.21-20.el8.x86_64                               1/5 
  Installing       : vim-filesystem-2:8.0.1763-19.el8_6.4.noarch            2/5 
  Installing       : vim-common-2:8.0.1763-19.el8_6.4.x86_64                3/5 
  Installing       : gpm-libs-1.20.7-17.el8.x86_64                          4/5 
  Running scriptlet: gpm-libs-1.20.7-17.el8.x86_64                          4/5 
  Installing       : vim-enhanced-2:8.0.1763-19.el8_6.4.x86_64              5/5 
  Running scriptlet: vim-enhanced-2:8.0.1763-19.el8_6.4.x86_64              5/5 
  Running scriptlet: vim-common-2:8.0.1763-19.el8_6.4.x86_64                5/5 
  Verifying        : gpm-libs-1.20.7-17.el8.x86_64                          1/5 
  Verifying        : vim-common-2:8.0.1763-19.el8_6.4.x86_64                2/5 
  Verifying        : vim-enhanced-2:8.0.1763-19.el8_6.4.x86_64              3/5 
  Verifying        : vim-filesystem-2:8.0.1763-19.el8_6.4.noarch            4/5 
  Verifying        : which-2.21-20.el8.x86_64                               5/5 

Installed:
  gpm-libs-1.20.7-17.el8.x86_64                                                 
  vim-common-2:8.0.1763-19.el8_6.4.x86_64                                       
  vim-enhanced-2:8.0.1763-19.el8_6.4.x86_64                                     
  vim-filesystem-2:8.0.1763-19.el8_6.4.noarch                                   
  which-2.21-20.el8.x86_64                                                      

Complete!
Removing intermediate container f88378120cc1
 ---> cb9eb843b319
Step 6/11 : RUN yum install -y net-tools
 ---> Running in 15b13dec8321
Last metadata expiration check: 0:00:29 ago on Sun Dec  8 07:29:48 2024.
Dependencies resolved.
================================================================================
 Package         Architecture Version                        Repository    Size
================================================================================
Installing:
 net-tools       x86_64       2.0-0.52.20160912git.el8       baseos       321 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 321 k
Installed size: 942 k
Downloading Packages:
net-tools-2.0-0.52.20160912git.el8.x86_64.rpm   262 kB/s | 321 kB     00:01    
--------------------------------------------------------------------------------
Total                                           101 kB/s | 321 kB     00:03     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                        1/1 
  Installing       : net-tools-2.0-0.52.20160912git.el8.x86_64              1/1 
  Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64              1/1 
  Verifying        : net-tools-2.0-0.52.20160912git.el8.x86_64              1/1 

Installed:
  net-tools-2.0-0.52.20160912git.el8.x86_64                                     

Complete!
Removing intermediate container 15b13dec8321
 ---> 2e79057963a9
Step 7/11 : RUN mkdir /opt/jdk
 ---> Running in 69bf76127e8d
Removing intermediate container 69bf76127e8d
 ---> 25f8d658823f
Step 8/11 : ADD jdk-17.0.12_linux-x64_bin.tar.gz /opt/jdk
 ---> 83d8b92be129
Step 9/11 : ENV JAVA_HOME /opt/jdk/jdk-17.0.12
 ---> Running in 1f4043adc4cb
Removing intermediate container 1f4043adc4cb
 ---> 3c05d8189cad
Step 10/11 : ENV PATH $JAVA_HOME/bin:$PATH
 ---> Running in 15d649530173
Removing intermediate container 15d649530173
 ---> c9f46f990422
Step 11/11 : CMD ["/bin/bash"]
 ---> Running in 02d2ee2073ee
Removing intermediate container 02d2ee2073ee
 ---> fb5b6a2e5b81
Successfully built fb5b6a2e5b81
Successfully tagged rockey8_jdk17:1.0.0

提示构建成功,查看一下自己构建的镜像

[root@localhost opt]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rockey8_jdk17       1.0.0               fb5b6a2e5b81        49 seconds ago      642MB
rockylinux          8.9                 c79048e50f5f        12 months ago       198MB

用交互模式用刚刚构建成的镜像运行一个容器,执行命令java -version验证打包进去的jdk和环境变量,构建成功!

[root@localhost opt]# docker run -it rockey8_jdk17:1.0.0
[root@a4703ffe3841 opt]# java -version
java version "17.0.12" 2024-07-16 LTS
Java(TM) SE Runtime Environment (build 17.0.12+8-LTS-286)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.12+8-LTS-286, mixed mode, sharing)

虚悬镜像

定义:REPOSITORYTAG都是<none>的镜像(dangling image),是由于构建和删除镜像时产生一些错误导致的,虚悬镜像会占用空间,因此需要清理掉它们

查出

docker image ls -f dangling=true

清理

docker image prune

Dockerfile
https://blog.liuzijian.com/post/929013b9-b765-b8c1-6343-84677774f987.html
作者
Liu Zijian
发布于
2024年11月24日
更新于
2025年1月8日
许可协议