常用的 Dockerfile 指令
1. 什么是 Dockerfile
Dockerfile 是基于一系列指令构建镜像的过程。
Dockerfile 和镜像的区别:
- 镜像:如同已做好的一道菜,例如 “佛跳墙”。
- Dockerfile:是一道菜的做法,例如 “佛跳墙” 的做法。使用 Dockerfile 使得镜像的传输过程更加方便。
2. Dockerfile 常用的指令
FROM
:指定基础镜像,后续指令以此镜像为基础。fromMAINTAINER
:设置镜像维护者的信息(该指令已逐渐被LABEL
替代)。maintainerLABEL
:为镜像添加元数据,如作者、版本等。labelADD
:将文件或目录从源路径复制到容器内的目标路径,还支持自动解压压缩包。addCOPY
:将文件或目录从源路径复制到容器内的目标路径。copyCMD
:为容器启动时提供默认命令。cmdENTRYPOINT
:配置容器启动后执行的命令。entrypointVOLUME
:创建一个挂载点,用于挂载外部数据卷。volumeEXPOSE
:声明容器运行时监听的端口。exposeWORKDIR
:设置工作目录,后续的RUN
、CMD
、COPY
等指令都在该目录下执行。workdirUSER
:指定运行容器时使用的用户或用户组。userONBUILD
:当该镜像被用作其他镜像的基础镜像时,触发执行的指令。onbuildHEALTHCHECK
:设置检查容器健康状态的命令。heal thcheckENV
:设置环境变量。envARG
:定义构建时使用的变量。argSHELL
:指定RUN
、CMD
和ENTRYPOINT
指令的 shell。shellRUN
:在容器中执行命令。run
CentOS8基础镜像之FROM-RUN-COPY-CMD指令案例
1. 创建工作目录
三个目录,centos,ubuntu,alpine三个linux系统
[root@elk92 ~]# mkdir -pv /haoshuaicongedu/dockerfile/{centos,ubuntu,alpine}
2. 准备 CentOS 镜像
[root@elk92 ~]# docker pull centos:7.9.2009
centos7.9.2009: Pulling from library/centos
2d473b07cdd5: Pull complete
Digest: sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
Status: Downloaded newer image for centos:7.9.2009
docker.io/library/centos:7.9.2009
[root@elk92 ~]#
3. 编写 Dockerfile
from指定基础镜像
copy拷贝文件到容器
run运行命令(最好先启动一下基础镜像,进去试一下指定的命令)编译镜像时的命令
cmd以后这个容器运行时的启动命令
[root@elk92 ~]# cd /haoshuaicongedu/dockerfile/centos/
[root@elk92 centos]#
[root@elk92 centos]# cat Dockerfile
# 使用 FROM 指令指定基础镜像,后续的所有指令都是围绕此镜像作为基础镜像
FROM centos:8.4.2105
# 拷贝文件到容器的指定路径
COPY nginx.repo /etc/yum.repos.d/
# 基于基础镜像启动一个容器,运行相关命令
RUN sed -e "s|^mirrorlist=|#mirrorlist=|g" \
-e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/8.4.2105|g" \
-i.bak \
/etc/yum.repos.d/CentOS-*.repo && \
yum -y install nginx && \
rm -rf /var/cache/ && \ # 这个是优化镜像大小,删除系统的缓存,如果运行时报错却少这个目录,创建即可
mkdir -p /var/cache/nginx/
# 容器运行时的启动命令
# CMD ["tail","-f","/etc/hosts"]
CMD ["nginx","-g","daemon off;"]
[root@elk92 centos]#
Docker容器的生命周期与其主进程的生命周期一致。如果主进程退出,容器会立即停止。tail-f命令会持续监听文件(如/etc/hosts)的变化并输出新增内容。由于tail-f是一个阻塞式命令(不会主动退出),它可以作为容器的主进程,使容器长期运行而不退出。
强制Nginx在前台运行
默认情况下,Nginx以守护进程模式(daemonon)运行,即启动后转入后台。但在容器中,这种模式会导致Docker认为主进程已结束,容器随即退出。通过-g “daemon of”参数,Nginx会被强制设置为前台运行模式,从而维持容器的生命周期。如果nginx死亡,那么容器也将停止
容器化最佳实践
在Docker中,推荐所有服务以前台模式运行,以便日志输出能被容器引擎捕获,同时避免因后台进程导致容器异常退出。这也是官方Nginx镜像的标准配置。
nginx.repo
文件内容:
[root@elk92 centos]# cat nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[root@elk92 centos]#
4. 编译镜像
docker build -t
编译镜像,在当前目录下
本质上docker就是启动一个镜像,然后运行一些命令,然后在打包导出这个镜像
[root@elk92 centos]# docker build -t haoshuaicongedu-linux96:v0.3 .
...
Step 4/4 : CMD ["nginx","-g","daemon off;"]
---> Running in 64fcee3dafbe
Removing intermediate container 64fcee3dafbe
---> cb2433559d05
Successfully built cb2433559d05
Successfully tagged haoshuaicongedu-linux96:v0.3
[root@elk92 centos]#
[root@elk92 centos]# docker image ls haoshuaicongedu-linux96
REPOSITORY TAG IMAGE ID CREATED SIZE
haoshuaicongedu-linux96 v0.3 cb2433559d05 About a minute ago 248MB
haoshuaicongedu-linux96 v0.2 9516678a3ba1 8 minutes ago 248MB
haoshuaicongedu-linux96 v0.1 c5271db1632c 13 minutes ago 284MB
[root@elk92 centos]#
5. 运行测试
[root@elk92 centos]# docker run -d --name haha haoshuaicongedu-linux96:v0.3
bf293cf4c5913d3855011610e13c9a3146977f7c593e06468d93501602a28144
[root@elk92 centos]#
[root@elk92 centos]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bf293cf4c591 haoshuaicongedu-linux96:v0.3 "nginx -g 'daemon of…" 4 seconds ago Up 2 seconds haha
[root@elk92 centos]#
[root@elk92 centos]# docker ps -l --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bf293cf4c5913d3855011610e13c9a3146977f7c593e06468d93501602a28144 haoshuaicongedu-linux96:v0.3 "nginx -g 'daemon off;'" 9 seconds ago Up 8 seconds haha
[root@elk92 centos]#
[root@elk92 centos]# docker container inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" haha
172.17.0.9
[root@elk92 centos]#
[root@elk92 centos]# curl 172.17.0.9
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
</html>
[root@elk92 centos]# docker ps -l --no-trunc # 不截断输出
Ubuntu基础镜像之MAINTAINER-LABEL指令案例
1. 拉取镜像
[root@elk92 ~]# docker pull ubuntu:24.04
24.04: Pulling from library/ubuntu
5a7813e071bf: Pull complete
Digest: sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04
[root@elk92 ~]#
2. 编写 Dockerfile
maintainer
label
[root@elk92 ubuntu]# cat Dockerfile
FROM ubuntu:24.04
RUN apt update && apt -y install curl && \
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null && \
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu noble nginx" \
| tee /etc/apt/sources.list.d/nginx.list && \
apt -y install nginx && \
rm -rf /var/cache/
# 声明作者信息,官方已经弃用,推荐使用 LABEL 来替代
MAINTAINER haoshuaicong haoshuaicong@163.com
# 给镜像打标签
LABEL a=haoshuaicong \
b=linux \
c=haoshuaicong \
email=haoshuaicong@163.com
# CMD ["tail","-f","/etc/hosts"]
CMD ["nginx","-g","daemon off;"]
[root@elk92 ubuntu]#
3. 编译镜像
[root@elk92 ubuntu]# docker build -t haoshuaicongedu-linux96:v1.2 .
Sending build context to Docker daemon 2.56kB
Step 1/5 : FROM ubuntu:24.04
---> a04dc4851cbc
Step 2/5 : RUN apt update && apt -y install curl && curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null && echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu noble nginx" | tee /etc/apt/sources.list.d/nginx.list && apt -y install nginx && rm -rf /var/cache/
---> Using cache
---> efef8513a9ac
Step 3/5 : MAINTAINER JasonYin yinzhengjie@haoshuaicongedu.com
---> Running in a5a57a1864ca
Removing intermediate container a5a57a1864ca
---> 76797490dd72
Step 4/5 : LABEL school=haoshuaicongedu class=linux96 auther=JasonYin email=yinzhengjie@haoshuaicongedu.com
---> Running in a53f79a8e8c1
Removing intermediate container a53f79a8e8c1
---> 9f0790473ccc
Step 5/5 : CMD ["nginx","-g","daemon off;"]
---> Running in 91cf3a5aa47a
Removing intermediate container 91cf3a5aa47a
---> 6d21180848aa
Successfully built 6d21180848aa
Successfully tagged haoshuaicongedu-linux96:v1.2
[root@elk92 ubuntu]#
4. 查看镜像信息
[root@elk92 ubuntu]# docker inspect -f "{{.Author}}" haoshuaicongedu-linux96:v1.2
JasonYin yinzhengjie@haoshuaicongedu.com
[root@elk92 ubuntu]#
[root@elk92 ubuntu]# docker inspect -f "{{.Config.Labels}}" haoshuaicongedu-linux96:v1.2
map[auther:JasonYin class:linux96 email:yinzhengjie@haoshuaicongedu.com org.opencontainers.image.ref.name:ubuntu org.opencontainers.image.version:24.04 school:haoshuaicongedu]
[root@elk92 ubuntu]#
5. 测试访问
[root@elk92 ubuntu]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5bae63c8f696 haoshuaicongedu-linux96:v1.2 "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds c1
[root@elk92 ubuntu]#
[root@elk92 ubuntu]# docker container inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" c1
172.17.0.2
[root@elk92 ubuntu]#
[root@elk92 ubuntu]# curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@elk92 ubuntu]#
alpine 基础镜像之 WORKDIR 指令案例 💋* * * * *
alpine的包安装工具:apk 。 使用apk add nginx安装
alpine是一个mini的linux系统,所以很多东西都没有需要使用apk安装
1. 编写 Dockerfile
注意:一定要写死tag版本号,不要用latest
workdir指定工作目录
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL a=haoshuaicong \
b=linux \
c=haoshuaicong \
email=haoshuaicong@163.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
# 连接容器时的工作目录,进去容器就在这个目录
WORKDIR /etc/nginx/conf.d/
CMD ["nginx","-g","daemon off;"]
[root@elk92 alpine]#
# openssh需要使用绝对路径使用
2. 编译
[root@elk92 alpine]# docker image build -t haoshuaicongedu-linux96:v2.0 .
3. 测试
略
容器启动多服务案例及 EXPOSE 指令
1. 编写 Dockerfile
也可以使用脚本启动容器,脚本里内容是启动nginx,启动sshd
COPY start.sh /
CMD [“/bin/sh”,”-x”,”/start.sh”]
expose 暴露容器内部的服务端口,最好是当前容器对外监听的服务
EXPOSE 80 22
[root@elk92 alpine]# cat start.sh
#!/bin/sh
# 定义 root 初始化密码
echo root:123456 | chpasswd
# 启动 sshd 服务
/usr/sbin/sshd
# 启动 nginx 服务
nginx -g "daemon off;"
[root@elk92 alpine]#
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
WORKDIR /etc/nginx/conf.d/
COPY start.sh /
# 暴露容器内部的服务端口,最好是当前容器对外监听的服务
EXPOSE 80 22
# CMD ["nginx","-g","daemon off;"]
CMD ["/bin/sh","-x","/start.sh"]
[root@elk92 alpine]#
2. 编译镜像
[root@elk92 alpine]# docker build -t haoshuaicongedu-linux96:v2.3 .
3. 测试运行
-P 表示随机端口映射,比如你的容器暴露了80端口和22端口 EXPOSE 80 22
0.0.0.0:32768->80/tcp
0.0.0.0:32769->22/tcp
[root@elk92 alpine]# docker run -d -P --name c6 haoshuaicongedu-linux96:v2.3
db65153cf3c05ae157a23929c32ec4f30a01f3c93e69c437f26375242f3d8bad
[root@elk92 alpine]#
[root@elk92 alpine]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db65153cf3c0 haoshuaicongedu-linux96:v2.3 "/bin/sh -x /start.sh" 4 seconds ago Up 3 seconds 0.0.0.0:32769->22/tcp, :::32769->22/tcp, 0.0.0.0:32768->80/tcp, :::32768->80/tcp c6
[root@elk92 alpine]#
[root@elk92 alpine]# curl 10.0.0.92:32768
[root@elk92 alpine]# ssh -p 32769 10.0.0.92
生成环境尽量选择较小的基础镜像
生产环境如果alpine不行做不到某些功能,再选择其他的镜像
[root@elk92 alpine]#
[root@elk92 alpine]# docker image ls haoshuaicongedu-linux96
REPOSITORY TAG IMAGE ID CREATED SIZE
haoshuaicongedu-linux96 v2.3 8154a438fff1 3 minutes ago 15.6MB
haoshuaicongedu-linux96 v2.2 b22e3c601e4b 6 minutes ago 15.6MB
haoshuaicongedu-linux96 v2.1 9412abe4c610 11 minutes ago 15.6MB
haoshuaicongedu-linux96 v2.0 b39d9de98cec 18 minutes ago 15.6MB ---》 alpine
haoshuaicongedu-linux96 v1.2 6d21180848aa 56 minutes ago 144MB
haoshuaicongedu-linux96 v1.1 8d2995ba3491 About an hour ago 144MB
haoshuaicongedu-linux96 v1.0 4022564d25a1 About an hour ago 146MB ---》ubuntu 24.04 lts
haoshuaicongedu-linux96 v0.3 cb2433559d05 2 hours ago 248MB
haoshuaicongedu-linux96 v0.2 9516678a3ba1 2 hours ago 248MB
haoshuaicongedu-linux96 v0.1 c5271db1632c 2 hours ago 284MB ---》CentOS 8
[root@elk92 alpine]#
容器启动多服务案例及 ENV 指令
1. 编写 Dockerfile
使用 docker run -e 传参,结合脚本修改root密码 ,判断用户有没有haoshuaicongEDU_ADMIN传入这个变量
在dockerfile中可以使用 ENV 来向容器传递变量
[root@elk92 alpine]# cat start.sh
#!/bin/sh
# 定义 root 初始化密码
if [ -v $haoshuaicongEDU_ADMIN ];
then
echo root:123456 | chpasswd
else
echo root:${haoshuaicongEDU_ADMIN} | chpasswd
fi
# 启动 sshd 服务
/usr/sbin/sshd
# 启动 nginx 服务
nginx -g "daemon off;"
[root@elk92 alpine]#
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
# 指定工作目录,将来启动容器时可以被 '-w' 选项覆盖
WORKDIR /etc/nginx/conf.d/
COPY start.sh /
# 向容器传递环境变量,将来启动容器时可以使用 -e 选项覆盖,所以密码是linux96
ENV haoshuaicongEDU_ADMIN="Linux96" \
address=ShaHe \
office=https://www.haoshuaicongedu.com
EXPOSE 80 22
CMD ["/bin/sh","-x","/start.sh"]
[root@elk92 alpine]#
2. 编译镜像
[root@elk92 alpine]# docker image build -t haoshuaicongedu-linux96:v2.4 .
3. 测试案例
# 如果不指定密码
[root@elk92 ~]# docker run -d --name c1 haoshuaicongedu-linux96:v2.4
3e4c879d6d2982a437779cae67a6a8996a562f26d3944950c960a602a2171d90
[root@elk92 ~]#
[root@elk92 ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e4c879d6d29 haoshuaicongedu-linux96:v2.4 "/bin/sh -x /start.sh" 3 seconds ago Up 3 seconds 22/tcp, 80/tcp c1
[root@elk92 ~]#
[root@elk92 ~]# docker container inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" c1
172.17.0.2
[root@elk92 ~]#
[root@elk92 ~]# curl 172.17.0.2
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@elk92 ~]#
[root@elk92 ~]# ssh 172.17.0.2 # 测试后,密码为 Linux96
[root@elk92 ~]#
[root@elk92 ~]# docker exec c1 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=3e4c879d6d29
haoshuaicongEDU_ADMIN=Linux96
address=ShaHe
office=https://www.haoshuaicongedu.com
HOME=/root
[root@elk92 ~]#
# 如果指定密码
[root@elk92 ~]# docker run -d --name c2 -e haoshuaicongEDU_ADMIN="haoshuaicongedu" haoshuaicongedu-linux96:v2.4
a72d0f2cb7b13e231c8e052f08eabaf4d34a0d8b830103bc62b11317635e7a8c
[root@elk92 ~]#
[root@elk92 ~]# docker exec c2 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=a72d0f2cb7b1
haoshuaicongEDU_ADMIN=haoshuaicongedu
address=ShaHe
office=https://www.haoshuaicongedu.com
HOME=/root
[root@elk92 ~]#
[root@elk92 ~]# docker container inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" c2
172.17.0.3
[root@elk92 ~]#
[root@elk92 ~]# ssh 172.17.0.3 # 测试后,密码为 haoshuaicongedu
面试题: RUN 和 CMD 的区别
构建镜像时,启动容器时
- CMD 是容器的启动命令
- RUN 是构建镜像阶段时做的一系列部署应用的操作:一般包含多个命令,容器启动时并不会调用该命令。
- RUN 和 CMD 指令数量不同:整个 Dockerfile 构建阶段,可以有多个 RUN 指令,但只能写一个 CMD 指令,如果写了多个 CMD 指令,则最后一个生效。
- CMD 指令可被用户替换:CMD 指令在容器运行时可以被用户替换。
CMD 指令在容器运行时可以被用户替换:
[root@elk92 alpine]# docker run -d --name c1 haoshuaicongedu-linux96:v2.4
b7a194188af7e6a035f527b961d1a5553484065718d12873ec12e9f524e6ecca
[root@elk92 alpine]#
[root@elk92 alpine]# docker ps -l # 默认启动命令/bin/sh -x /start.sh
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7a194188af7 haoshuaicongedu-linux96:v2.4 "/bin/sh -x /start.sh" 4 seconds ago Up 3 seconds 22/tcp, 80/tcp c1
[root@elk92 alpine]#
# 在命令后面加上命令,启动命令就被替换了。tail -f /etc/hosts
[root@elk92 alpine]# docker run -d --name c2 haoshuaicongedu-linux96:v2.4 tail -f /etc/hosts
74841aca71d4b1106eb7bf506d21e57e35e6a8dab4ae023eda3106f971bb14ab
[root@elk92 alpine]#
[root@elk92 alpine]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
74841aca71d4 haoshuaicongedu-linux96:v2.4 "tail -f /etc/hosts" 3 seconds ago Up 1 second 22/tcp, 80/tcp c2
[root@elk92 alpine]#
alpine 基础镜像之 ENTRYPOINT 指令案例
1. 编写 Dockerfile
entrypoint 指定容器的启动命令,但并不会被替换,如果用户指定了启动命令,将作为参数传递。’
也就是说cmd 参数可以被覆盖,可以当做entrypoint的传参变量
[root@elk92 alpine]# cat start.sh
#!/bin/sh
# 这里使用了,cmd和entrypoint的特性,实现传参修改密码
# 定义 root 初始化密码
if [ -n "$1" ]
then
echo root:$1| chpasswd
elif [ -n "$haoshuaicongEDU_ADMIN" ]
then
echo root:${haoshuaicongEDU_ADMIN} | chpasswd
else
echo root:123456 | chpasswd
fi
# 启动 sshd 服务
/usr/sbin/sshd
# 启动 nginx 服务
nginx -g "daemon off;"
[root@elk92 alpine]#
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
# 指定工作目录,将来启动容器时可以被 '-w' 选项覆盖
WORKDIR /etc/nginx/conf.d/
COPY start.sh /
# 向容器传递环境变量,将来启动容器时可以使用 -e 选项覆盖
ENV haoshuaicongEDU_ADMIN="Linux96" \
address=ShaHe \
office=https://www.haoshuaicongedu.com
EXPOSE 80 22
# 指定容器的启动命令,但并不会被替换,如果用户指定了启动命令,将作为参数传递。
ENTRYPOINT ["/bin/sh","-x","/start.sh"]
# 当 ENTRYPOINT 和 CMD 一起使用时,CMD 将作为参数传递给 ENTRYPOINT,且 CMD 参数可以被替换。
#ENTRYPOINT ["tail"]
#CMD ["-f","/etc/hosts"]
[root@elk92 alpine]#
# 也就是 tail -f /etc/hosts 就是说可以搭配使用
# 也就是说cmd 参数可以被覆盖,可以当做entrypoint的传参变量,假如是stop 命令就是/start.sh stop
2. 编译镜像
[root@elk92 alpine]# cat build.sh
#!/bin/bash
docker image build -t haoshuaicongedu-linux96:v2.$1 .
docker image ls haoshuaicongedu-linux96
docker container rm -f `docker container ps -qa`
docker run -dP --name c1 haoshuaicongedu-linux96:v2.$1
docker ps -l
[root@elk92 alpine]#
[root@elk92 alpine]# chmod +x build.sh
[root@elk92 alpine]#
[root@elk92 alpine]# ./build.sh 7
3. 测试请问 root 密码多少?
[root@elk92 alpine]# docker run -e haoshuaicongEDU_ADMIN="xixi" -dP --name c3 haoshuaicongedu-linux96:v2.7 haoshuaicongedu
dc8272848741ed1aa745bd6fe315a1e75ff12207e4ae80c8e222d879506cbc6b
[root@elk92 alpine]#
[root@elk92 alpine]# docker exec c3 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=dc8272848741
haoshuaicongEDU_ADMIN=xixi
address=ShaHe
office=https://www.haoshuaicongedu.com
HOME=/root
[root@elk92 alpine]#
[root@elk92 alpine]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc8272848741 haoshuaicongedu-linux96:v2.7 "/bin/sh -x /start.s…" 36 seconds ago Up 36 seconds 0.0.0.0:32775->22/tcp, :::32775->22/tcp, 0.0.0.0:32774->80/tcp, :::32774->80/tcp c3
[root@elk92 alpine]#
在这个测试中,由于启动容器时指定了命令参数 haoshuaicongedu
,根据 start.sh
脚本的逻辑,root 密码会被设置为 haoshuaicongedu
。
nginx 的变量案例
参考链接
- https://nginx.org/en/docs/varindex.html
1. 编写 Dockerfile
[root@elk92 alpine]# ll
total 24
drwxr-xr-x 2 root root 4096 Mar 21 15:26 ./
drwxr-xr-x 5 root root 4096 Mar 21 09:26 ../
-rwxr-xr-x 1 root root 206 Mar 21 14:55 build.sh*
-rw-r--r-- 1 root root 207 Mar 21 15:25 default.conf
-rw-r--r-- 1 root root 1056 Mar 21 15:26 Dockerfile
-rw-r--r-- 1 root root 292 Mar 21 14:52 start.sh
[root@elk92 alpine]#
# 404改成200测试,加上nginx内置变量客户端ip,容器的ip。
[root@elk92 alpine]# cat default.conf
server {
listen 80 default_server;
location / {
return 200 "<h1>ClientIP: $remote_addr, Container IP: $server_addr</h1>";
}
location = /404.html {
internal;
}
}
[root@elk92 alpine]#
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
# 指定工作目录,将来启动容器时可以被 '-w' 选项覆盖
WORKDIR /etc/nginx/http.d
COPY default.conf /etc/nginx/http.d
COPY start.sh /
# 向容器传递环境变量,将来启动容器时可以使用 -e 选项覆盖
ENV haoshuaicongEDU_ADMIN="Linux96" \
address=ShaHe \
office=https://www.haoshuaicongedu.com
EXPOSE 80 22
# 指定容器的启动命令,但并不会被替换,如果用户指定了启动命令,将作为参数传递。
ENTRYPOINT ["/bin/sh","-x","/start.sh"]
# 当 ENTRYPOINT 和 CMD 一起使用时,CMD 将作为参数传递给 ENTRYPOINT,且 CMD 参数可以被替换。
#ENTRYPOINT ["tail"]
#CMD ["-f","/etc/hosts"]
[root@elk92 alpine]#
[root@elk92 alpine]# ./build.sh 8
...
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
044994c27dfd haoshuaicongedu-linux96:v2.8 "/bin/sh -x /start.sh" Less than a second ago Up Less than a second 0.0.0.0:32777->22/tcp, :::32777->22/tcp, 0.0.0.0:32776->80/tcp, :::32776->80/tcp c1
2. 测试效果
[root@elk92 alpine]# curl 10.0.0.92:32776
<h1>ClientIP: 10.0.0.92, Container IP: 172.17.0.2</h1>
ADD 指令之游戏镜像制作案例
ADD 功能类似于 COPY,但支持从远程 URL 下载文件,还可以自动解压压缩文件。
1. 编写 Dockerfile
[root@elk92 alpine]# ll
total 12764
drwxr-xr-x 2 root root 4096 Mar 21 15:57 ./
drwxr-xr-x 5 root root 4096 Mar 21 09:26 ../
-rwxr-xr-x 1 root root 206 Mar 21 14:55 build.sh*
-rw-r--r-- 1 root root 207 Mar 21 15:25 default.conf
-rw-r--r-- 1 root root 1106 Mar 21 15:57 Dockerfile
-rw-r--r-- 1 root root 256 Mar 21 15:40 games.conf
-rw-r--r-- 1 root root 919045 Mar 21 15:34 haoshuaicongedu-killbird.tar.gz
-rw-r--r-- 1 root root 12118590 Mar 21 15:35 haoshuaicongedu-zombie-master.tar.gz
-rw-r--r-- 1 root root 292 Mar 21 14:52 start.sh
[root@elk92 alpine]#
[root@elk92 alpine]# cat games.conf
server {
listen 0.0.0.0:80;
root /usr/share/nginx/killbird/;
server_name xixi.haoshuaicongedu.com;
}
server {
listen 0.0.0.0:80;
root /usr/share/nginx/zombie-master/;
server_name haha.haoshuaicongedu.com;
}
[root@elk92 alpine]#
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
WORKDIR /etc/nginx/http.d
COPY default.conf /etc/nginx/http.d
COPY games.conf /etc/nginx/http.d
COPY start.sh /
#COPY haoshuaicongedu-killbird.tar.gz haoshuaicongedu-zombie-master.tar.gz /
#RUN tar xf /haoshuaicongedu-killbird.tar.gz -C /usr/share/nginx && \
# tar xf /haoshuaicongedu-zombie-master.tar.gz -C /usr/share/nginx && \
# rm -f /haoshuaicongedu-zombie-master.tar.gz /haoshuaicongedu-killbird.tar.gz
# 可以自动解压 tar 包,其他格式和 COPY 一样,仅做拷贝。
ADD haoshuaicongedu-killbird.tar.gz /usr/share/nginx
ADD haoshuaicongedu-zombie-master.tar.gz /usr/share/nginx
ENV haoshuaicongEDU_ADMIN="Linux96" \
address=ShaHe \
office=https://www.haoshuaicongedu.com
EXPOSE 80 22
ENTRYPOINT ["/bin/sh","-x","/start.sh"]
[root@elk92 alpine]#
[root@elk92 alpine]# ./build.sh 11
...
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c5b700a3de4 haoshuaicongedu-linux96:v2.11 "/bin/sh -x /start.sh" 1 second ago Up Less than a second 0.0.0.0:32783->22/tcp, :::32783->22/tcp, 0.0.0.0:32782->80/tcp, :::32782->80/tcp c1
2. windows 测试【hosts 文件需要解析】
3.镜像大小优化
# 如果dockerfile使用rm。会发现空间没有变小
RUN rm -f /haoshuaicongedu-zombie-master.tar.gz /haoshuaicongedu-killbird.tar.gz
# 可以使用history来查看构建时的记录,来排查每一步的大小,然后优化
# docker image history haoshuaicong-alpine:v2.9
[root@elk92 alpine]# docker image history haoshuaicong-ubt24.04:v1.0
IMAGE CREATED CREATED BY SIZE COMMENT
ac978ca5200c 4 hours ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
33dc46634be1 4 hours ago /bin/sh -c #(nop) LABEL school=haoshuaicongedu cl… 0B
52f1c8b37509 4 hours ago /bin/sh -c #(nop) MAINTAINER haoshuaicong 1… 0B
873510e68f74 4 hours ago /bin/sh -c apt update && apt -y install curl… 66.4MB
a04dc4851cbc 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:6df775300d76441aa… 78.1MB
<missing> 7 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B
<missing> 7 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ARG RELEASE 0B
[root@elk92 alpine]#
# 为什么rm没有变小
没执行一共docker指令,都是一个分层,所以rm的时候是一个独立的层,只是在rm的那一层删除了,tar那一层没删除
所有镜像时多个层一起构建的结果,已经发生的事无法改变,原因是,本地宿主机有缓存,所以删不掉
所以改用ADD即可
VOLUME 指令实现宿主机路径的数据持久化
volume 启动容器时,对该目录做数据的持久化,相当于: docker run -v /usr/share/nginx -v /etc/nginx/http.d …
1. 编写 Dockerfile
[root@elk92 alpine]# cat Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
WORKDIR /etc/nginx/http.d
COPY default.conf /etc/nginx/http.d
COPY games.conf /etc/nginx/http.d
COPY start.sh /
ADD haoshuaicongedu-killbird.tar.gz /usr/share/nginx
ADD haoshuaicongedu-zombie-master.tar.gz /usr/share/nginx
ENV haoshuaicongEDU_ADMIN="Linux96" \
address=ShaHe \
office=https://www.haoshuaicongedu.com
EXPOSE 80 22
# 启动容器时,对该目录做数据的持久化,相当于: docker run -v /usr/share/nginx -v /etc/nginx/http.d ...
VOLUME /usr/share/nginx /etc/nginx/http.d
ENTRYPOINT ["/bin/sh","-x","/start.sh"]
[root@elk92 alpine]#
2. 测试案例
[root@elk92 alpine]# docker volume ls
DRIVER VOLUME NAME
[root@elk92 alpine]# ./build.sh 12
...
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9ddbaf78acad haoshuaicongedu-linux96:v2.14 "/bin/sh -x /start.sh" Less than a second ago Up Less than a second 0.0.0.0:32789->22/tcp, :::32789->22/tcp, 0.0.0.0:32788->80/tcp, :::32788->80/tcp c1
[root@elk92 alpine]#
[root@elk92 alpine]# docker volume ls
DRIVER VOLUME NAME
local 01e408304686b2bafbb2c5e2759cf4a2447da10ad28f7c956dbb54869e17480b
local 80d3ddfbdfd5c72d247d3a25e32d15a95e3557bc63d01ee3b587d5b37f831c07
[root@elk92 alpine]#
[root@elk92 alpine]# docker inspect -f "{{(index .Mounts 0).Source}}" c1
/var/lib/docker/volumes/80d3ddfbdfd5c72d247d3a25e32d15a95e3557bc63d01ee3b587d5b37f831c07/_data
[root@elk92 alpine]#
[root@elk92 alpine]# docker inspect -f "{{(index .Mounts 1).Source}}" c1
/var/lib/docker/volumes/01e408304686b2bafbb2c5e2759cf4a2447da10ad28f7c956dbb54869e17480b/_data
[root@elk92 alpine]#
[root@elk92 alpine]# ll /var/lib/docker/volumes/80d3ddfbdfd5c72d247d3a25e32d15a95e3557bc63d01ee3b587d5b37f831c07/_data
total 16
drwxr-xr-x 2 root root 4096 Mar 21 16:28 ./
drwx-----x 3 root root 4096 Mar 21 16:28 ../
-rw-r--r-- 1 root root 207 Mar 21 15:25 default.conf
-rw-r--r-- 1 root root 256 Mar 21 15:40 games.conf
[root@elk92 alpine]#
[root@elk92 alpine]# ll /var/lib/docker/volumes/01e408304686b2bafbb2c5e2759cf4a2447da10ad28f7c956dbb54869e17480b/_data
total 20
drwxr-xr-x 4 root root 4096 Mar 21 16:28 ./
drwx-----x 3 root root 4096 Mar 21 16:28 ../
-rw-r--r-- 1 root root 342 Mar 17 02:48 http-default_server.conf
drwxr-xr-x 3 root root 4096 Mar 21 16:28 killbird/
drwxr-xr-x 6 root root 4096 Mar 21 16:28 zombie-master/
[root@elk92 alpine]#
查看镜像构建历史信息
通过查看镜像的历史信息,可以看到在哪个指令上占用空间最大,从而帮我们定义将来要优化的位置。
1. 查看 MySQL 构建镜像历史信息
[root@elk92 alpine]# docker image ls mysql
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0.36-oracle f5f171121fa3 12 months ago 603MB
[root@elk92 alpine]#
[root@elk92 alpine]# docker image history mysql:8.0.36-oracle
IMAGE CREATED CREATED BY SIZE COMMENT
f5f171121fa3 12 months ago CMD ["mysqld"] 0B buildkit.dockerfile.v0
<missing> 12 months ago EXPOSE map[3306/tcp:{} 33060/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 12 months ago ENTRYPOINT ["docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c ln -s usr/local/bin/docker-en… 34B buildkit.dockerfile.v0
<missing> 12 months ago COPY docker-entrypoint.sh /usr/local/bin/ # … 13.5kB buildkit.dockerfile.v0
<missing> 12 months ago VOLUME [/var/lib/mysql] 0B buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eux; microdnf install -… 286MB buildkit.dockerfile.v0
<missing> 12 months ago ENV MYSQL_SHELL_VERSION=8.0.36-1.el8 0B buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eu; { echo '[mysql-to… 215B buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eux; microdnf install -… 185MB buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eu; { echo '[mysql8.0… 225B buildkit.dockerfile.v0
<missing> 12 months ago ENV MYSQL_VERSION=8.0.36-1.el8 0B buildkit.dockerfile.v0
<missing> 12 months ago ENV MYSQL_MAJOR=8.0 0B buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eux; key='BCA4 3417 C3B… 3.17kB buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eux; microdnf install -… 13.6MB buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eux; arch="$(uname -m)"… 2.36MB buildkit.dockerfile.v0
<missing> 12 months ago ENV GOSU_VERSION=1.17 0B buildkit.dockerfile.v0
<missing> 12 months ago RUN /bin/sh -c set -eux; groupadd --system … 2.77kB buildkit.dockerfile.v0
<missing> 12 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 12 months ago /bin/sh -c #(nop) ADD file:c53be7373aad45b6a… 116MB
[root@elk92 alpine]#
2. 查看咱们自己的镜像构建信息
[root@elk92 alpine]# docker image history haoshuaicongedu-linux96:v2.14
IMAGE CREATED CREATED BY SIZE COMMENT
191f43d0bd10 7 minutes ago /bin/sh -c #(nop) ENTRYPOINT ["/bin/sh" "-x… 0B
92eda69b02e2 7 minutes ago /bin/sh -c #(nop) VOLUME [/usr/share/nginx … 0B
e4ed6d67fc18 35 minutes ago /bin/sh -c #(nop) EXPOSE 22 80 0B
746dccaba620 35 minutes ago /bin/sh -c #(nop) ENV haoshuaicongEDU_ADMIN=Linux… 0B
035463fc1601 35 minutes ago /bin/sh -c #(nop) ADD file:b646f75f64fb465a6… 12.8MB
2b23387745cd 35 minutes ago /bin/sh -c #(nop) ADD file:320a16d1009c0c35c… 1.24MB
768d1389b46c 50 minutes ago /bin/sh -c #(nop) COPY file:e0def6850a027039… 292B
273c02ccc105 50 minutes ago /bin/sh -c #(nop) COPY file:322bd9fb40651738… 256B
37505c569d90 About an hour ago /bin/sh -c #(nop) COPY file:bb6e9fb704ec2df0… 207B
3e0381afeb14 About an hour ago /bin/sh -c #(nop) WORKDIR /etc/nginx/http.d 0B
478d0751f882 5 hours ago /bin/sh -c sed -i 's#dl-cdn.alpinelinux.org#… 7.73MB
e4f752d16fc4 5 hours ago /bin/sh -c #(nop) LABEL school=haoshuaicongedu cl… 0B
2df6941c47dc 5 hours ago /bin/sh -c #(nop) MAINTAINER Jason Yin 0B
aded1e1a5b37 5 weeks ago CMD ["/bin/sh"] 0B buildkit.dockerfile.v0
<missing> 5 weeks ago ADD alpine-minirootfs-3.21.3-x86_64.tar.gz /… 7.83MB buildkit.dockerfile.v0
[root@elk92 alpine]#
以上所有指令必须学会,基础指令🍉🥙🌮🥫🍘
-------------------------> 必会
FROM
RUN
MAINTAINER
LABEL
ENV
COPY
ADD
WORDIR
EXPOSE
VOLUME
CMD
ENTRYPOINT
------------------> 看心情
HEALTHCHECK指令
USER
ONBUILD
SHELL
ARG
HEALTHCHECK 指令实现服务的健康检查
1. 编写 Dockerfile
FROM alpine:3.21.3
MAINTAINER Jason Yin
LABEL school=haoshuaicongedu \
class=linux96 \
email=yinzhengjie@haoshuaicongedu.com
RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories && \
apk update && apk add nginx openssh curl && \
ssh-keygen -A && \
sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \
rm -rf /var/cache/
WORKDIR /etc/nginx/http.d
COPY default.conf /etc/nginx/http.d
COPY games.conf /etc/nginx/http.d
COPY start.sh /
ADD haoshuaicongedu-killbird.tar.gz /usr/share/nginx
ADD haoshuaicongedu-zombie-master.tar.gz /usr/share/nginx
ENV haoshuaicongEDU_ADMIN="Linux96" \
address=ShaHe \
office=https://www.haoshuaicongedu.com
EXPOSE 80 22
VOLUME /usr/share/nginx /etc/nginx/http.d
# 对容器做健康检查,参考链接:
# https://docs.docker.com/reference/dockerfile/#healthcheck
# CMD后面执行的命令一定要在容器存在,若不存在则检测失败!CMD可以是脚本
# 测试,通过curl。每1秒检查一次服务状态,单次检查超时1秒即视为失败,容器启动后10秒内允许初始化不触发健康判定,连续3次检查失败则标记容器为不健康。
HEALTHCHECK --interval=1s --timeout=1s --start-period=10s --retries=3 \
CMD curl -f http://localhost/ || exit 1
ENTRYPOINT ["/bin/sh","-x","/start.sh"]
2. 编译测试
关注 Up 4 seconds (healthy)
[root@elk92 alpine]# ./build.sh 15
...
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0fedd2068146 haoshuaicongedu-linux96:v2.15 "/bin/sh -x /start.sh" 1 second ago Up Less than a second (health: starting) 0.0.0.0:32795->22/tcp, :::32795->22/tcp, 0.0.0.0:32794->80/tcp, :::32794->80/tcp c1
[root@elk92 alpine]#
[root@elk92 alpine]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0fedd2068146 haoshuaicongedu-linux96:v2.15 "/bin/sh -x /start.sh" 5 seconds ago Up 4 seconds (healthy) 0.0.0.0:32795->22/tcp, :::32795->22/tcp, 0.0.0.0:32794->80/tcp, :::32794->80/tcp c1
[root@elk92 alpine]#
以普通用户的身份运行服务 USER
user :运行服务时以哪个用户运行,容器必须存在该用户且运行时必须有相应文件的权限。
场景:比如kibana服务,只能使用kibana用户启动
编写 Dockerfile
FROM alpine:3.21.3
RUN adduser -D linux96 && \
echo linux96:123456 | chpasswd linux96
# 运行服务时以哪个用户运行,容器必须存在该用户且运行时必须有相应文件的权限。
# 如果报错,就是没有这个用户,创建用户使用adduser -D不设置密码,不交互
USER linux96
CMD ["tail","-f","/etc/hosts"]
构建和运行容器
[root@elk92 test]# docker build -t demo:v0.1 .
[root@elk92 test]#
[root@elk92 test]# docker run -d --name c2 demo:v0.1
91c8f96af97f1aaff436a90abc0865c2027a775e81b5bb1f955a03b1791c888b
[root@elk92 test]#
[root@elk92 test]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
91c8f96af97f demo:v0.1 "tail -f /etc/hosts" 3 seconds ago Up 2 seconds c2
[root@elk92 test]#
[root@elk92 test]# docker exec -it c2 sh
/ $ whoami
linux96
/ $
/ $ ps -ef
PID USER TIME COMMAND
1 linux96 0:00 tail -f /etc/hosts
7 linux96 0:00 sh
14 linux96 0:00 ps -ef
/ $
ARG 在构建阶段生效的环境变量
编写 Dockerfile
FROM alpine:3.21.3
# 在构建阶段时生效,运行容器阶段失效,在构建阶段时可以使用--build-arg进行覆盖。
ARG school=haoshuaicongedu \
class=linux96
# 在构建阶段时生效,运行容器阶段依旧生效,运行容器阶段时使用-e进行覆盖。
ENV address=ShaHe \
classroom=教室6
# 创建几个文件,测试
RUN adduser -D linux96 && \
echo linux96:123456 | chpasswd linux96 && \
touch /home/linux96/${school} /home/linux96/${class} /home/linux96/${address} /home/linux96/${classroom}
# 运行服务时以哪个用户运行,容器必须存在该用户且运行时必须有相应文件的权限。
USER linux96
CMD ["tail","-f","/etc/hosts"]
构建和运行容器
[root@elk92 test]# docker build -t demo:v0.2 .
[root@elk92 test]#
[root@elk92 test]# docker run -it demo:v0.2 sh
/ $ ls -l /home/linux96/
total 0
-rw-r--r-- 1 root linux96 0 Mar 21 09:05 ShaHe
-rw-r--r-- 1 root linux96 0 Mar 21 09:05 linux96
-rw-r--r-- 1 root linux96 0 Mar 21 09:05 haoshuaicongedu
-rw-r--r-- 1 root linux96 0 Mar 21 09:05 教室6
/ $
/ $ env
HOSTNAME=56dfbde22abb
SHLVL=1
HOME=/home/linux96
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
classroom=教室6
address=ShaHe
PWD=/
/ $
[root@elk92 test]# docker build -t demo:v0.3 --build-arg school=laonanhai .
[root@elk92 test]#
[root@elk92 test]# docker run -it demo:v0.3 sh
/ $ ls -l /home/linux96/
total 0
-rw-r--r-- 1 root linux96 0 Mar 21 09:07 ShaHe
-rw-r--r-- 1 root linux96 0 Mar 21 09:07 laonanhai
-rw-r--r-- 1 root linux96 0 Mar 21 09:07 linux96
-rw-r--r-- 1 root linux96 0 Mar 21 09:07 教室6
/ $
面试题:ARG 和 ENV 的区别
相同点
- 都可以设置环境变量。
- 都可以被覆盖,
ARG
使用--build-arg
覆盖,ENV
使用-e
或--env
覆盖。
不同点
- 生命周期不同:
ARG
仅在构建阶段生效。ENV
在构建阶段和容器运行阶段都生效。
ONBUILD 基础镜像触发器
1. 编写基础镜像的 Dockerfile
FROM alpine:3.21.3
# 在构建阶段时生效,运行容器阶段失效,在构建阶段时可以使用--build-arg进行覆盖。
ARG school=haoshuaicongedu \
class=linux96
# 在构建阶段时生效,运行容器阶段依旧生效,运行容器阶段时使用-e进行覆盖。
ENV address=ShaHe \
classroom=教室6
RUN adduser -D linux96 && \
echo linux96:123456 | chpasswd linux96 && \
touch /home/linux96/${school} /home/linux96/${class} /home/linux96/${address} /home/linux96/${classroom}
# 运行服务时以哪个用户运行,容器必须存在该用户且运行时必须有相应文件的权限。
# USER linux96
# 定义基础镜像触发器,说白了,谁将来引用咱们当前的镜像就会触发定义的Dockefile指令。
# 只要基于我的镜像构建新的镜像,就会执行指定的操作,使用不会有。
ONBUILD RUN mkdir /haoshuaicongedu-linux96 && touch /haoshuaicongedu-linux96/xixi.log
ONBUILD RUN mkdir /haoshuaicongedu-laonanhai && touch /haoshuaicongedu-laonanhai/haha.txt
ONBUILD LABEL blog=https://www.cnblogs.com/yinzhengjie \
office=https://www.haoshuaicongedu.com/
ONBUILD WORKDIR /etc/
CMD ["tail","-f","/etc/hosts"]
2. 编译镜像
[root@elk92 test]# docker build -t demo:v0.4 .
3. 查看镜像
查看镜像信息
[root@elk92 test]# for i in `seq 0 3`; do docker inspect -f "{{( index .Config.OnBuild $i)}}" demo:v0.4;done
RUN mkdir /haoshuaicongedu-linux96 && touch /haoshuaicongedu-linux96/xixi.log
RUN mkdir /haoshuaicongedu-laonanhai && touch /haoshuaicongedu-laonanhai/haha.txt
LABEL blog=https://www.cnblogs.com/yinzhengjie office=https://www.haoshuaicongedu.com/
WORKDIR /etc/
4. 基于基础镜像构建新镜像
-f 表示指定dockerfile文件,不指定默认会去找Dockerfile的文件
[root@elk92 test]# docker build -t demo:v0.5 -f linux96.dockerfile .
5. 测试验证
[root@elk92 test]# docker exec -it c33 sh
/etc # ls -l /
total 64
drwxr-xr-x 2 root root 4096 Feb 13 23:04 bin
drwxr-xr-x 5 root root 340 Mar 21 09:51 dev
drwxr-xr-x 1 root root 4096 Mar 21 09:51 etc
drwxr-xr-x 1 root root 4096 Mar 21 09:05 home
drwxr-xr-x 6 root root 4096 Feb 13 23:04 lib
drwxr-xr-x 5 root root 4096 Feb 13 23:04 media
drwxr-xr-x 2 root root 4096 Feb 13 23:04 mnt
drwxr-xr-x 2 root root 4096 Mar 21 09:50 haoshuaicongedu-laonanhai
drwxr-xr-x 2 root root 4096 Mar 21 09:50 haoshuaicongedu-linux96
-rw-r--r-- 1 root root 0 Mar 21 09:50 haoshuaicongedu-xixi-haha
drwxr-xr-x 2 root root 4096 Feb 13 23:04 opt
dr-xr-xr-x 333 root root 0 Mar 21 09:51 proc
drwx------ 1 root root 4096 Mar 21 09:51 root
drwxr-xr-x 3 root root 4096 Feb 13 23:04 run
drwxr-xr-x 2 root root 4096 Feb 13 23:04 sbin
drwxr-xr-x 2 root root 4096 Feb 13 23:04 srv
dr-xr-xr-x 13 root root 0 Mar 21 09:51 sys
drwxrwxrwt 2 root root 4096 Feb 13 23:04 tmp
drwxr-xr-x 7 root root 4096 Feb 13 23:04 usr
drwxr-xr-x 11 root root 4096 Feb 13 23:04 var
/etc #
/etc # ls -l /haoshuaicongedu-linux96/
total 0
-rw-r--r-- 1 root root 0 Mar 21 09:50 xixi.log
/etc #
/etc # ls -l /haoshuaicongedu-laonanhai/
total 0
-rw-r--r-- 1 root root 0 Mar 21 09:50 haha.txt
/etc #
/etc #
[root@elk92 test]#
[root@elk92 test]# docker inspect -f "{{.Config.Labels.blog}}" demo:v0.5
https://www.cnblogs.com/yinzhengjie
[root@elk92 test]#
[root@elk92 test]# docker inspect -f "{{.Config.Labels.office}}" demo:v0.5
https://www.haoshuaicongedu.com/
SHELL 解释器及 STOPSIGNAL 退出信号量
Dockerfile 内容
shell :声明shell解释器,一般情况下系统有多个shell时可以根据情况指定
stopsignal 9 信号量,表示容器退出的模式,跟kill一样(基本不用)
FROM alpine:3.21.3
# 声明shell解释器,一般情况下系统有多个shell时可以根据情况而定。windows有多个shell环境时可能会用到。
# SHELL ["/bin/ash","-c"]
SHELL ["/bin/sh","-c"]
# 声明容器退出时的发送的信号量。一般情况下不常用。
STOPSIGNAL 9
# 在构建阶段时生效,运行容器阶段失效,在构建阶段时可以使用--build-arg进行覆盖。
ARG school=haoshuaicongedu \
class=linux96
# 在构建阶段时生效,运行容器阶段依旧生效,运行容器阶段时使用-e进行覆盖。
ENV address=ShaHe \
classroom=教室6
RUN adduser -D linux96 && \
echo linux96:123456 | chpasswd linux96 && \
touch /home/linux96/${school} /home/linux96/${class} /home/linux96/${address} /home/linux96/${classroom}
# 运行服务时以哪个用户运行,容器必须存在该用户且运行时必须有相应文件的权限。
# USER linux96
# 定义基础镜像触发器,说白了,谁将来引用咱们当前的镜像就会触发定义的Dockefile指令。
ONBUILD RUN mkdir /haoshuaicongedu-linux96 && touch /haoshuaicongedu-linux96/xixi.log
ONBUILD RUN mkdir /haoshuaicongedu-laonanhai && touch /haoshuaicongedu-laonanhai/haha.txt
ONBUILD LABEL blog=https://www.cnblogs.com/yinzhengjie \
office=https://www.haoshuaicongedu.com/
ONBUILD WORKDIR /etc/
CMD ["tail","-f","/etc/hosts"]
构建镜像
[root@elk92 test]# docker build -t demo:v0.6 .
dockerfile指令总结
# 指定基础镜像,触发ONBUILD指令,用于多价段构建
FROM
# 执行命令并创建新的镜像层
RUN
# (已弃用,推荐使用LABEL):声明作者信息
MAINTAINER
# 添加元数据(键值对)。打标签
LABEL
# 设置环境变量
ENV
# 定义构建时的参数(仅在构建阶段有效)。也是设置环境变量
ARG
# 复制本地文件到镜像
COPY
# 类似COPY,但支持自动解压和URL下载。也是拷贝
ADD
# 设置后续命令的工作目录
WORKDIR
# 声明容器监听的端口
EXPOSE
# 定义数据卷挂载点
VOLUME
# 设置容器启动后默认执行的命令(可被覆盖)
CMD
# 设置容器启动时的主命令(不可被覆盖)
ENTRYPOINT
----------->
# 定义容器健康检查逻辑
HEALTHCHECK
# 指定运行命令的用户身份
USER
# 延迟执行指令(用于父镜像的继承场景)
ONBUILD
# 覆盖默认的Shell程序(如/bin/sh)
SHELL
# 退出服务信号量
STOPSIGNAL
说明:
新旧命令对比:docker container ls 是较新的语法,docker ps 是旧版命令,两者功能一致。
MAINTAINER vs LABEL:MAINTAINER 已弃用,建议用 LABEL maintainer="your_info" 替代。
CMD vs ENTRYPOINT:CMD 定义默认命令,可被 docker run 覆盖;ENTRYPOINT 定义入口命令,通常与CMD配合使用。