Docker file构建镜像18个指令技巧

常用的 Dockerfile 指令

1. 什么是 Dockerfile

Dockerfile 是基于一系列指令构建镜像的过程。

Dockerfile 和镜像的区别:

  • 镜像:如同已做好的一道菜,例如 “佛跳墙”。
  • Dockerfile:是一道菜的做法,例如 “佛跳墙” 的做法。使用 Dockerfile 使得镜像的传输过程更加方便。

2. Dockerfile 常用的指令

  • FROM:指定基础镜像,后续指令以此镜像为基础。from
  • MAINTAINER:设置镜像维护者的信息(该指令已逐渐被 LABEL 替代)。maintainer
  • LABEL:为镜像添加元数据,如作者、版本等。label
  • ADD:将文件或目录从源路径复制到容器内的目标路径,还支持自动解压压缩包。add
  • COPY:将文件或目录从源路径复制到容器内的目标路径。copy
  • CMD:为容器启动时提供默认命令。cmd
  • ENTRYPOINT:配置容器启动后执行的命令。entrypoint
  • VOLUME:创建一个挂载点,用于挂载外部数据卷。volume
  • EXPOSE:声明容器运行时监听的端口。expose
  • WORKDIR:设置工作目录,后续的 RUNCMDCOPY 等指令都在该目录下执行。workdir
  • USER:指定运行容器时使用的用户或用户组。user
  • ONBUILD:当该镜像被用作其他镜像的基础镜像时,触发执行的指令。onbuild
  • HEALTHCHECK:设置检查容器健康状态的命令。heal thcheck
  • ENV:设置环境变量。env
  • ARG:定义构建时使用的变量。arg
  • SHELL:指定 RUNCMDENTRYPOINT 指令的 shell。shell
  • RUN:在容器中执行命令。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配合使用。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇