Dockerfile
Dockerfile概述
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
从应用软件的角度来看,Dockerfile,Docker镜像,Docker容器分别代表软件的三个不同阶段
- Dockerfile是软件的原材料
- Docker镜像是软件的交付品
- Docker容器可以认为是软件的运行态
![]()
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及运维和部署,合力充当Docker体系的基石。
Dockerfile定义了进程需要的一切东西,Dockerfile涉及的内容包括执行代码或者文件,环境变量,依赖包,运行时环境,动态链接库,操作系统发行版,服务进程和内核进程(当应用程序需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等。
Docker镜像,在用Dockerfile定义了一个构建文件之后,docker build时会产生一个Docker镜像,当运行Docker镜像时,会开始真正的提供服务。
Docker容器,是直接提供服务的进程。
Dockerfile构建过程:
- docker从基础镜像运行一个容器
- 执行一条指令,并对容器进行修改
- 执行类似
docker commit的操作,提交一个新的镜像层 - docker再基于刚刚提交的镜像运行一个新容器
- 继续执行Dockerfile的下一条指令,直到所有指令都执行完成
Dockerfile的保留字指令
Dockerfile每个保留字指令均为大写,且后面至少跟随一个参数,指令从上到下顺序执行,用#表示注释。
FROM基本出现在第一行,意思是要构建的新镜像继承于或者说基于哪个已存在的镜像。
FROM ubuntu:20.04MAINTAINR维护者信息(姓名和邮箱地址)
ENV用于在构建镜像的过程中设置环境变量,这个环境变量可以在后续的任何
RUN指令中使用,就像在命令前面指定了环境变量一样,也可以在其他指令中直接使用这些环境变量,比如WORKDIR $JAVA_HOMEENV PATH="/usr/local/bin:${PATH}"RUN容器构建(docker build)时需要运行的命令,分为
shell和exec两种格式shell
RUN apt-get update && apt-get install -y curlexec
RUN ["apt-get", "install", "-y", "curl"]EXPOSE声明容器运行时应该开放的端口。它不会自动开启端口,但为外部用户或其他容器提供信息
EXPOSE 80 443WORKDIR指定在创建容器后,终端默认登录进来的工作目录,当执行
docker run -it 镜像ID /bash进入容器内部的时候,会默认落脚在哪个目录里USER指定镜像以什么用户去执行,如果不指定,默认是
rootUSER myuserVOLUME容器数据卷,用于数据的保存和持久化,声明容器内的哪个目录需要在运行时挂载数据卷到宿主机上
VOLUME ["/data"]ADDADD功能相比COPY更加强大,将宿主机内的文件拷贝进镜像,如果源文件是.tar、.tar.gz等压缩格式的文件,ADD会自动解压到目标路径。ADD还可以从指定的URL下载文件并复制到容器内。ADD <宿主机源路径> <容器内目标路径>COPY仅仅执行文件的复制,不支持自动解压或下载
COPY <宿主机源路径> <容器内目标路径>CMD指定容器启动后要做的事情,支持
shell和exec两种格式,还支持参数列表格式,如果指定了ENTRYPOINT指令,CMD就会被用来指定具体的运行参数注意事项
1.
RUN和CMD的区别:RUN是构建镜像时执行,CMD是docker run容器启动时执行2.Dockerfile中可以有多个
CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换例如:tomcat的Dockerfile的最后一行是
CMD ["catalina.sh", "run"],那么使用docker run -it tomcat /bin/bash命令启动这个镜像时,容器会启动,但是tomcat就不会被启动,因为被run后的命令/bin/bash替换掉了,故容器启动后会运行/bin/bashENTRYPOINT类似于
CMD命令,但是不会被docker run后的命令覆盖,而且还会把docker run后的命令当作命令行参数传递给ENTRYPOINT指令指定的程序ENTRYPOINT ["可执行文件", "参数1", "参数2", ......]ENTRYPOINT可以和CMD一起用,一般是变参才会使用到CMD,这里的CMD等同于是在给ENTRYPOINT传参,当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,它们两个组合后会变成<ENTRYPOINT> "<CMD>"案例:
FROM nginxENTRYPOINT ["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,新镜像内新增vim,net-tools组件,并将下载好的jdk17拷贝进去,并设置jdk相关的环境变量,让这个镜像构建的容器自带原版镜像不默认安装的一些工具,并且自带jdk17
找到一个空文件夹,vim Dockerfile编辑文件将构建命令写进去
FROM rockylinux:8.9MAINTAINER lzj2023@foxmail.comENV MYPATH /optWORKDIR $MYPATHRUN 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/jdkENV JAVA_HOME /opt/jdk/jdk-17.0.12ENV PATH $JAVA_HOME/bin:$PATHCMD ["/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.8MBStep 1/11 : FROM rockylinux:8.98.9: Pulling from library/rockylinux9088cdb84e39: Pull complete Digest: sha256:9794037624aaa6212aeada1d28861ef5e0a935adaf93e4ef79837119f2a2d04cStatus: Downloaded newer image for rockylinux:8.9 ---> c79048e50f5fStep 2/11 : MAINTAINER lzj2023@foxmail.com ---> Running in 9c40b7e878e1Removing intermediate container 9c40b7e878e1 ---> e58d03a7ebaeStep 3/11 : ENV MYPATH /opt ---> Running in d8448a9b4329Removing intermediate container d8448a9b4329 ---> da5da26abbe3Step 4/11 : WORKDIR $MYPATH ---> Running in ddf20f025c3fRemoving intermediate container ddf20f025c3f ---> 2fe907e79d95Step 5/11 : RUN yum -y install vim ---> Running in f88378120cc1Rocky 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 MInstalling 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 kTransaction Summary================================================================================Install 5 PackagesTotal download size: 7.8 MInstalled size: 30 MDownloading 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-rockyofficialKey imported successfullyRunning transaction checkTransaction check succeeded.Running transaction testTransaction 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 ---> cb9eb843b319Step 6/11 : RUN yum install -y net-tools ---> Running in 15b13dec8321Last 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 kTransaction Summary================================================================================Install 1 PackageTotal download size: 321 kInstalled size: 942 kDownloading 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 checkTransaction check succeeded.Running transaction testTransaction 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 ---> 2e79057963a9Step 7/11 : RUN mkdir /opt/jdk ---> Running in 69bf76127e8dRemoving intermediate container 69bf76127e8d ---> 25f8d658823fStep 8/11 : ADD jdk-17.0.12_linux-x64_bin.tar.gz /opt/jdk ---> 83d8b92be129Step 9/11 : ENV JAVA_HOME /opt/jdk/jdk-17.0.12 ---> Running in 1f4043adc4cbRemoving intermediate container 1f4043adc4cb ---> 3c05d8189cadStep 10/11 : ENV PATH $JAVA_HOME/bin:$PATH ---> Running in 15d649530173Removing intermediate container 15d649530173 ---> c9f46f990422Step 11/11 : CMD ["/bin/bash"] ---> Running in 02d2ee2073eeRemoving intermediate container 02d2ee2073ee ---> fb5b6a2e5b81Successfully built fb5b6a2e5b81Successfully tagged rockey8_jdk17:1.0.0提示构建成功,查看一下自己构建的镜像
[root@localhost opt]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZErockey8_jdk17 1.0.0 fb5b6a2e5b81 49 seconds ago 642MBrockylinux 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 -versionjava version "17.0.12" 2024-07-16 LTSJava(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)虚悬镜像
定义:REPOSITORY和TAG都是<none>的镜像(dangling image),是由于构建和删除镜像时产生一些错误导致的,虚悬镜像会占用空间,因此需要清理掉它们
查出
docker image ls -f dangling=true清理
docker image prune