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的保留字指令}
Dockerfile每个保留字指令均为大写,且后面至少跟随一个参数,指令从上到下顺序执行,用#
表示注释。
FROM
{#FROM}
基本出现在第一行,意思是要构建的新镜像继承于或者说基于哪个已存在的镜像。
FROM ubuntu:20.04
MAINTAINR
{#MAINTAINR}
维护者信息(姓名和邮箱地址)
ENV
{#ENV}
用于在构建镜像的过程中设置环境变量,这个环境变量可以在后续的任何RUN
指令中使用,就像在命令前面指定了环境变量一样,也可以在其他指令中直接使用这些环境变量,比如WORKDIR $JAVA_HOME
ENV PATH="/usr/local/bin:${PATH}"
RUN
{#RUN}
容器构建(docker build)时需要运行的命令,分为shell
和exec
两种格式
shell
RUN apt-get update && apt-get install -y curl
exec
CMD ["可执行文件", "参数1", "参数2", ......]
EXPOSE
{#EXPOSE}
声明容器运行时应该开放的端口。它不会自动开启端口,但为外部用户或其他容器提供信息
EXPOSE 80 443
WORKDIR
{#WORKDIR}
指定在创建容器后,终端默认登录进来的工作目录,当执行docker run -it 镜像ID /bash
进入容器内部的时候,会默认落脚在哪个目录里
USER
{#USER}
指定镜像以什么用户去执行,如果不指定,默认是root
USER myuser
VOLUME
{#VOLUME}
容器数据卷,用于数据的保存和持久化,声明容器内的哪个目录需要在运行时挂载数据卷到宿主机上
VOLUME ["/data"]
ADD
{#ADD}
ADD
功能相比COPY
更加强大,将宿主机内的文件拷贝进镜像,如果源文件是.tar
、.tar.gz
等压缩格式的文件,ADD
会自动解压到目标路径。ADD
还可以从指定的URL下载文件并复制到容器内。
ADD <宿主机源路径> <容器内目标路径>
COPY
{#COPY}
仅仅执行文件的复制,不支持自动解压或下载
COPY <宿主机源路径> <容器内目标路径>
CMD
{#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/bash
ENTRYPOINT
{#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构建镜像}
编写一个Dockerfile,用于构建一个自带Java17环境的RockyLinux9镜像,构建的镜像基于发行版rockylinux:8.9
,新镜像内新增vim
,net-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)
虚悬镜像 {#虚悬镜像}
定义:REPOSITORY
和TAG
都是<none>
的镜像(dangling image),是由于构建和删除镜像时产生一些错误导致的,虚悬镜像会占用空间,因此需要清理掉它们
查出
docker image ls -f dangling=true
清理
docker image prune