Docker-仓库-镜像制作

一、Harbor 仓库

https://goharbor.io/https://goharbor.io/

1.Harbor仓库简介

  • "Harbor" 是一个用于管理和部署容器化应用程序的开源仓库管理系统,主要用于存储、管理和分发 Docker 容器镜像。
  • 它提供了一个企业级的 Docker 镜像仓库,支持多种安全特性、镜像管理和访问控制。

2.安装需求

服务器配置需求

有两种安装方式,在线安装和离线安装

下载安装包,注意rc是预售版本,还不完善

3.安装Harbor仓库

(1)解压软件包

复制代码
[root@localhost ~]# tar xvf harbor-offline-installer-v2.13.2.tgz -C /usr/local/
[root@localhost ~]# cd /usr/local/harbor/
[root@localhost harbor]# ll
总用量 659252
-rw-r--r-- 1 root root      3646  7月 31 10:48 common.sh
-rw-r--r-- 1 root root 675032342  7月 31 10:48 harbor.v2.13.2.tar.gz
-rw-r--r-- 1 root root     14688  7月 31 10:48 harbor.yml.tmpl
-rwxr-xr-x 1 root root      1975  7月 31 10:48 install.sh
-rw-r--r-- 1 root root     11347  7月 31 10:48 LICENSE
-rwxr-xr-x 1 root root      2211  7月 31 10:48 prepare

 common.sh               # 共用脚本 
 harbor.v2.13.2.tar.gz   # Harbor 离线镜像      
 harbor.yml.tmpl         # template 模板 
 harbor.yml              # 配置文件  
 install.sh              # 脚本   安装 Harbor , 执行一次
 LICENSE
 prepare                 # 脚本  harbor.yml 

(2)修改yml配置文件

复制代码
[root@localhost harbor]# mkdir -p /data/registry
[root@localhost harbor]# mv harbor.yml.tmpl harbor.yml
[root@localhost harbor]# vi harbor.yml 
# 可以改成域名或ip,但建议使用域名,这样内网外网用户都可以访问
hostname: reg.xxhf.com
# 先注释掉这里,不配置公钥
# https related config
# https:
  # https port for harbor, default is 443
  # port: 443
  # The path of cert and key files for nginx
  # certificate: /your/certificate/path
  # private_key: /your/private/key/path
  # enable strong ssl ciphers (default: false)
  # strong_ssl_ciphers: false
# 设置账户密码,这里的密码最好用复杂密码
harbor_admin_password: "*id,4g5EPuB@B@xwEhYsISEn4JIS"
# 设置数据库密码,最好和账户密码不一致
database:
  # The password for the user('postgres' by default) of Harbor DB. Change this before any production use.
  password: uNIloGyBmezYl0f@SKosjOlbyL4DWUDtEjzuSvYn

# 修改镜像存储位置,生产环境要挂载一块较大的磁盘
data_volume: /data/registry

设置复杂密码(可以调整位数)

复制代码
[root@localhost harbor]# pwmake 128
*id,4g5EPuB@B@xwEhYsISEn4JIS
[root@localhost harbor]# pwmake 192
uNIloGyBmezYl0f@SKosjOlbyL4DWUDtEjzuSvYn

(3)执行安装脚本

复制代码
# 直到所有容器都启动成功,才可以访问harbor
[root@localhost harbor]# ./install.sh

注:记得将域名注册到真实机的hosts文件当中

复制代码
192.168.5.100 reg.xxhf.cc

(4)通过域名访问web服务

注:访问时需要注意,目前的浏览器大多都默认使用https协议,而我们搭建的harbor仓库目前使用的是http协议,因此在使用域名访问时记得检查使用正确的协议http

(5)上传镜像

复制代码
# 连接harbor仓库时,可以使用服务器,也可以使用客户端,客户端需要安装docker服务
[root@localhost ~]# echo "192.168.5.100 reg.xxhf.cc" >> /etc/hosts
[root@localhost ~]# vi /etc/docker/daemon.json
# 将域名注册到不安全的仓库当中
"insecure-registries": ["reg.xxhf.cc"]

[root@localhost harbor]# systemctl restart docker
# 重启docker之后,harbor仓库可能会掉线,需要重新启动

# 登录
[root@localhost ~]# docker login reg.xxhf.cc
Username: admin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores

Login Succeeded
[root@localhost ~]# docker tag nginx:1.22.1 reg.xxhf.cc/xxhf/nginx:v1
# 上传镜像,域名+地址+容器名(需要提前设置)
[root@localhost ~]# docker push reg.xxhf.cc/xxhf/nginx:v1
The push refers to repository [reg.xxhf.cc/xxhf/nginx]
9543dec06aa8: Pushed 
ccf4f419ba49: Pushed 
21f8452ebfb1: Pushed 
25bbf4633bb3: Pushed 
a4f34e6fb432: Pushed 
3af14c9a24c9: Pushed 
v1: digest: sha256:9081064712674ffcff7b7bdf874c75bcb8e5fb933b65527026090dacda36ea8b size: 1570

4.配置harbor-https协议

注:若想要使harbor仓库支持https协议,那么它的域名(reg.xxhf.cc)就需要有对应的证书和私钥

(1)证书申请

注:阿里云和腾讯云都可以申请免费的证书

(2)安装证书

复制代码
# 下载证书到本机
[root@localhost ~]# ls
anaconda-ks.cfg  cat.sh  dockerfile-example.tgz  harbor-offline-installer-v2.13.2.tgz  reg.xxhf.cc_nginx.zip
[root@localhost ~]# unzip reg.xxhf.cc_nginx.zip
[root@localhost ~]# cd /usr/local/harbor/
[root@localhost harbor]# mkdir certs
[root@localhost harbor]# mv /root/reg.xxhf.cc_nginx/reg.xxhf.cc_bundle.crt certs/
[root@localhost harbor]# mv /root/reg.xxhf.cc_nginx/reg.xxhf.cc.key certs/
# 在配置文件中添加证书
[root@localhost harbor]# vi harbor.yml
# https related config
https:
  # https port for harbor, default is 443
  port: 443
  # The path of cert and key files for nginx
  certificate: /usr/local/harbor/certs/reg.xxhf.cc_bundle.crt
  private_key: /usr/local/harbor/certs/reg.xxhf.cc.key
  # enable strong ssl ciphers (default: false)
  # strong_ssl_ciphers: false
# 使配置生效
[root@localhost harbor]# ./prepare 
# 重启服务
[root@localhost harbor]# docker compose down
[root@localhost harbor]# docker compose up -d

注:如果过程报错,可以通过查看日志纠错

复制代码
[root@localhost harbor]# docker compose logs -f

补充:如何查看文件内容是否一致?

复制代码
# diff命令测试,如果一致则没有任何反应
[root@localhost reg.xxhf.cc_nginx]# diff reg.xxhf.cc_bundle.crt reg.xxhf.cc_bundle.pem

# md5sum命令测试,如果哈希值一致,则内容一致
[root@localhost reg.xxhf.cc_nginx]# md5sum reg.xxhf.cc_bundle.crt
e7ad2c8d1157cd63b60d0e4f088708b3  reg.xxhf.cc_bundle.crt
[root@localhost reg.xxhf.cc_nginx]# md5sum reg.xxhf.cc_bundle.pem
e7ad2c8d1157cd63b60d0e4f088708b3  reg.xxhf.cc_bundle.pem

(3)再次访问web服务

注:可以发现此时的harbor仓库已经支持https协议了

二、Harbor仓库常用功能

1.定时删除镜像

注:根据要求配置保留最近几个版本的镜像,配置定时执行周期即可

2.实现高可用

注:通过复制管理,创建复制,在复数的harbor仓库上推送镜像,实现高可用

3.漏洞扫描

注:在镜像上传的时候,扫描镜像的漏洞(在安装时添加trivy,也可以在配置文件中修改)

三、镜像制作

1.镜像的分层

  • 容器创建时需要指定镜像,每一个镜像都有唯一的镜像ID
  • Docker的镜像通过联合文件系统(UFS)将各层文件系统叠加在一起(这一点在下载镜像的过程中就可以体现出来)

2.镜像特性

注:已有的分层只能读、不能修改;上层镜像优先级大于底层镜像;容器和宿主机共用bootfs

3.Docker commit制作镜像

复制代码
# 添加命令工具
[root@localhost ~]# docker run -it rockylinux:9
[root@0f3aed80969d /]# dnf -y install wget iproute

# 另开一个窗口,将添加命令后的容器制作镜像
[root@localhost ~]# docker commit 3782b435f6ac rocky9:v1
sha256:2647e88790d1b8921b015ba87108f8e57b4ebfd198fcfe03324324729c27071c
[root@localhost ~]# docker images rocky9:v1
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
rocky9       v1        2647e88790d1   22 seconds ago   213MB
# 查看原来的镜像,可以发现数据变多了
[root@localhost ~]# docker images rockylinux:9
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
rockylinux   9         9cc24f05f309   23 months ago   176MB

注:新添加的命令变成了分层,这就是镜像分层的概念;优点是创建简单,缺点是创建好的层无法修改,需要重新制作镜像

4.Dockerfile制作镜像

(1)Dockerfile简介

  • Dockerfile 是一个文本格式的配置文件,我们可以使用Dockerfile来快速创建自定义的镜像
  • Dockerfile模版包在上传的资源中

(2)创建Dockerfile

复制代码
[root@localhost ~]# vim Dockerfile

# Base image

FROM rockylinux:9

LABEL authors="chijinjing@xinxianghf.com"


RUN  dnf -y install wget iproute  && dnf clean all    #这里做了缓存的清除

CMD /usr/sbin/nginx

(3)制作镜像

复制代码
[root@localhost ~]# docker build -t rocky9:v2 .
[root@localhost ~]# docker images rocky9:v2
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
rocky9       v2        cf533c72574a   33 seconds ago   186MB

注:可以看到制作出来的镜像要比之前制作的要小上一些,是因为清除了缓存

(4)修改配置文件

复制代码
[root@localhost ~]# vim Dockerfile
# Base image

FROM rockylinux:9

LABEL authors="chijinjing@xinxianghf.com"


RUN  dnf -y install wget iproute
RUN  dnf clean all

CMD /usr/sbin/nginx

[root@localhost ~]# docker build -t rocky9:v3 .
[root@localhost ~]# docker images rocky9:v3
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
rocky9       v3        c6d239ac0de5   17 seconds ago   213MB

注:可以看到在查看镜像时又恢复到了原来的体积

原因:镜像是分层的,已有的分层只能读,不能修改,而每运行一条 RUN 指令,镜像添加新的一层,并提交

(5)指令说明

(6)ARG&&ENV

  • ARG:定义创建镜像过程中使用的变量(只能在构建时使用,变成容器就没有了,支持在构建时传参数)
  • **ENV:**声明镜像内服务监听的端口(生命周期较长 , 在构建时可以使用 ,变成容器还可以使用,不支持在构建时传参)

需求:安装 nginx-1:1.26.1 ,不允许 修改 Dockerfile 文件

当前配置文件

复制代码
[root@localhost dockerfile-arg-env]# pwd
/root/dockerfile-example/dockerfile-arg-env
[root@localhost dockerfile-arg-env]# vi Dockerfile 
[root@localhost ~]# vi Dockerfile
# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

ARG VERSION=1.26.0
ENV NGINX_VERSION=1.26.1

#EXPOSE 80

WORKDIR /data

# Add nginx yum repo
COPY nginx.repo /etc/yum.repos.d/nginx.repo

# Install nginx
RUN  dnf -y install nginx-1:$VERSION-1.el9.ngx.x86_64 && dnf clean all
#RUN  yum -y install nginx-1:$NGINX_VERSION-1.el9.ngx.x86_64 && yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# Start nginx daemon
CMD ["/usr/sbin/nginx"]

执行命令

复制代码
[root@localhost dockerfile-arg-env]# docker build -t nginx-arg:1.26.1 --build-arg VERSION=1.26.1 .

5.指定环境变量

(1)运行mysql容器

复制代码
[root@localhost ~]# docker run -d mysql
0f0684eb9a38219265e0a35e77b8ed31cb4012f62c64b91913ba1d70815e24f8
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED             STATUS             PORTS      NAMES
2c3987c8d9a3   nginx          "/docker-entrypoint...."   16 minutes ago      Up 16 minutes      80/tcp     gracious_shannon
3782b435f6ac   rockylinux:9   "/bin/bash"               About an hour ago   Up About an hour              sweet_blackwell
a647f85bc327   redis          "docker-entrypoint.s..."   2 hours ago         Up 2 hours         6379/tcp   gracious_blackburn

注:发现容器并没有启动,我们查看日志发现需要配置环境变量

(2)指定环境变量

注:我们可以在启动容器的时候指定环境变量的值,这次可以成功启动

复制代码
[root@localhost ~]# docker run -e MYSQL_ROOT_PASSWORD=123456 -d mysql
2b001bfb03470ca8d34530489b43f119982405ad14dc619ef8a4077fa5083c98
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED             STATUS             PORTS                 NAMES
2b001bfb0347   mysql          "docker-entrypoint.s..."   5 seconds ago       Up 5 seconds       3306/tcp, 33060/tcp   epic_allen
2c3987c8d9a3   nginx          "/docker-entrypoint...."   21 minutes ago      Up 21 minutes      80/tcp                gracious_shannon
3782b435f6ac   rockylinux:9   "/bin/bash"               About an hour ago   Up About an hour                         sweet_blackwell
a647f85bc327   redis          "docker-entrypoint.s..."   2 hours ago         Up 2 hours         6379/tcp              gracious_blackburn

6.Dockerfile指令诠释

(1)FROM

  • 指定所创建镜像的 基础镜像
  • 格式为 FROM <image> [AS <name>] FROM <image>:<tag> [AS <name>] FROM <image>@<digest> [AS <name>]
  • 任何 Dockerfile 中第一条指令必须为FROM指令

配置文件:

复制代码
[root@localhost dockerfile-from]# pwd
/root/dockerfile-example/dockerfile-from
[root@localhost dockerfile-from]# vi Dockerfile

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

# Install tools 
RUN  dnf -y install telnet wget
RUN  dnf clean all

CMD ["/bin/bash"]

制作镜像:

复制代码
[root@localhost dockerfile-from]# docker build -t centos7 .
[root@localhost dockerfile-from]# docker run -it centos7 
[root@875049732e95 /]# 

(2)ARG

  • 定义创建镜像过程中使用的变量。
  • 格式为 ARG <name>[=<default value>]
  • 在执行 docker build 时,可以通过 --build-arg [=] 来为变量赋值。当镜像编译成功后,ARG 指定的变量将不再存在(ENV 指定的变量将在镜像中保留)

配置文件:

复制代码
[root@localhost dockerfile-arg-env]# pwd
/root/dockerfile-example/dockerfile-arg-env
[root@localhost dockerfile-arg-env]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

ARG VERSION=1.26.0
ENV NGINX_VERSION=1.26.1

#EXPOSE 80

WORKDIR /data

# Add nginx yum repo
COPY nginx.repo /etc/yum.repos.d/nginx.repo

# Install nginx
RUN  dnf -y install nginx-1:$VERSION-1.el9.ngx.x86_64 && dnf clean all
#RUN  yum -y install nginx-1:$NGINX_VERSION-1.el9.ngx.x86_64 && yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# Start nginx daemon
CMD ["/usr/sbin/nginx"]

制作镜像:

  • ARG 的变量可以在 docker build 的过程中使用 --build-arg 参数修改变量的值

    [root@localhost dockerfile-arg-env]# docker build -t nginx:1.26.2 --build-arg VERSION=1.26.1 .
    [root@localhost dockerfile-arg-env]# docker run -it nginx:1.26.1 /bin/bash
    [root@160f4b765b88 data]# nginx -v
    nginx version: nginx/1.26.1

(3)LABEL

  • LABEL 指令可以为生成的镜像添加元数据标签信息。
  • 格式为LABEL <key>=<value> <key>=<value> <key>=<value> ...

配置文件:

复制代码
[root@localhost dockerfile-label]# pwd
/root/dockerfile-example/dockerfile-label
[root@localhost dockerfile-label]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

LABEL date="2025-02-06"
LABEL description="This is a demo image that based on Rockylinux9."

CMD ["/bin/bash"]

制作镜像:

复制代码
[root@localhost dockerfile-label]# docker build -t nginx-label:v1 .
[root@localhost dockerfile-label]# docker inspect  nginx-label:v1
            "Labels": {
                "authors": "chijinjing@xinxianghf.com",
                "date": "2025-02-06",
                "description": "This is a demo image that based on Rockylinux9."
            }

(4)EXPOSE

  • 声明镜像内服务监听的端口。
  • 该指令只是起到 声明作用,并不会自动完成端口映射
  • 格式为 EXPOSE <port> [<port>/<protocol>...]

例如:

复制代码
EXPOSE  80 443

(5)ENV

  • 指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在
  • 指令指定的环境变量在运行时可以被覆盖掉,如 docker run --env <key>=<value> image_name
  • 格式为 ENV <key>=<value> ...

配置文件:

复制代码
[root@localhost dockerfile-arg-env]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

ARG VERSION=1.26.0
ENV NGINX_VERSION=1.26.1

EXPOSE 80

WORKDIR /data

# Add nginx yum repo
COPY nginx.repo /etc/yum.repos.d/nginx.repo

# Install nginx
#RUN  dnf -y install nginx-1:$VERSION-1.el9.ngx.x86_64 && dnf clean all
RUN  yum -y install nginx-1:$NGINX_VERSION-1.el9.ngx.x86_64 && yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# Start nginx daemon
CMD ["/usr/sbin/nginx"]

制作镜像:

复制代码
[root@localhost dockerfile-arg-env]# docker build -t nginx-env:1.26.3 .
# 未修改前
[root@localhost dockerfile-arg-env]# docker run -it nginx-env:1.26.3 bash                                                                                    
[root@c8a57df52d88 data]# echo $nginx-env
-env
[root@c8a57df52d88 data]# echo $NGINX_VERSION
1.26.1
[root@c8a57df52d88 data]# exit
exit
# 修改后
[root@localhost dockerfile-arg-env]# docker run -it --env NGINX_VERSION=1.26.3 nginx-env:1.26.3 bash
[root@8f1cd0620779 data]# echo $NGINX_VERSION
1.26.3

(6)ENTRYPOINT

  • 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。
  • 支持两种格式:
  1. ENTRYPOINT ["executable", "param1", "param2"]: 使用 exec 执行; 建议使用这种方式
  2. ENTRYPOINT command param1 param2: 在 shell 终端中执行。
  • 每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效
在Shell中执行:
复制代码
[root@localhost dockerfile-entrypoint]# pwd
/root/dockerfile-example/dockerfile-entrypoint
[root@localhost dockerfile-entrypoint]# ls
Dockerfile  Dockerfile2  Dockerfile2-cmd  Dockerfile-cmd  nginx.repo
[root@localhost dockerfile-entrypoint]# vi Dockerfile

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

ENV NGINX_VERSION=1.26.1

# Add nginx yum repo
COPY nginx.repo /etc/yum.repos.d/nginx.repo

# Install nginx
RUN  dnf -y install nginx-1:$NGINX_VERSION-1.el9.ngx.x86_64 && yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# Start nginx daemon
ENTRYPOINT /usr/sbin/nginx

制作镜像:

复制代码
[root@localhost dockerfile-entrypoint]# docker build -t entrypoint-shell .
exec 调用执行:
复制代码
[root@localhost dockerfile-entrypoint]# vi Dockerfile2

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

ENV NGINX_VERSION=1.26.1

# Add nginx yum repo
COPY nginx.repo /etc/yum.repos.d/nginx.repo

# Install nginx
RUN  dnf -y install nginx-1:$NGINX_VERSION-1.el9.ngx.x86_64 && dnf clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# Start nginx daemon
ENTRYPOINT ["/usr/sbin/nginx"]

制作镜像:

复制代码
[root@localhost dockerfile-entrypoint]# docker build -t entrypoint-exec -f Dockerfile2  .
比较两者区别:
复制代码
[root@localhost dockerfile-entrypoint]# docker run -d entrypoint-shell                                                                                       
a9582643491afb0e5bdf158fde5b7380ab75ce3c8be426d4c4ced44ac28ccc5a
[root@localhost dockerfile-entrypoint]# docker run -d entrypoint-exec
b9f92a4d842b1721fc51ff2840287594a526ef9b028d0d324df838aa437ae980

[root@localhost dockerfile-entrypoint]# docker ps --no-trunc
CONTAINER ID                                                       IMAGE              COMMAND                        CREATED          STATUS          PORTS     NAMES
b9f92a4d842b1721fc51ff2840287594a526ef9b028d0d324df838aa437ae980   entrypoint-exec    "/usr/sbin/nginx"              27 seconds ago   Up 26 seconds             festive_brattain
a9582643491afb0e5bdf158fde5b7380ab75ce3c8be426d4c4ced44ac28ccc5a   entrypoint-shell   "/bin/sh -c /usr/sbin/nginx"   36 seconds ago   Up 35 seconds             gallant_raman

(7)VOLUME 卷

  • 创建一个数据卷挂载点
  • 格式为 VOLUME ["/data"]
  • 运行容器时可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保持的数据

(8)USER

  • 指定运行容器时的用户名或 UID,后续的 RUN 等指令也会使用指定的用户身份
  • 格式为 USER daemon
  • 当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在Dockerfile中创建所需要的用户

配置文件:

复制代码
[root@localhost dockerfile-user]# pwd
/root/dockerfile-example/dockerfile-user
[root@localhost dockerfile-user]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

# Add user
RUN groupadd -r redis && useradd -r -g redis redis
USER redis

CMD ["/bin/bash"]

制作镜像:

复制代码
[root@localhost dockerfile-user]# docker build -t  user-redis .
[root@localhost dockerfile-user]#  docker run -it user-redis whoami
redis

(9)WORKDIR

  • 为 RUN、CMD、ENTRYPOINT 指令配置工作目录
  • 格式为 WORKDIR /path/to/workdir
  • 可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径

例如:

复制代码
WORKDIR /a   # mkdir /a && cd /a ​
WORKDIR b    # mkdir b &&  cd b    /a/b ​
WORKDIR c​
RUN pwd   # /a/b/c
最终路径为/a/b/c。​
因此,为了避免出错,推荐WORKDIR指令中只使用绝对路径。

配置文件:

复制代码
[root@localhost dockerfile-workdir]# pwd
/root/dockerfile-example/dockerfile-workdir
[root@localhost dockerfile-workdir]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

WORKDIR /data
COPY app.json .

WORKDIR /data/app/
COPY app.jar .

WORKDIR /data/applog/

CMD ["/bin/bash"]

制作镜像:

复制代码
[root@localhost dockerfile-workdir]# docker build -t workdir:v1 .
[root@localhost dockerfile-workdir]# docker run -it workdir:v1 pwd
/data/applog

(10)ONBUILD

  • 指定当基于所生成镜像创建子镜像时,自动执行的操作指令。
  • 格式为 ONBUILD [INSTRUCTION]
  • 使用 docker build 命令创建子镜像 ChildImage 时(FROM ParentImage),会首先执行 ParentImage 中配置的 ONBUILD 指令
  • ONBUILD 指令在自动编译、检查等操作的基础镜像时,十分有用

配置文件:

复制代码
[root@localhost dockerfile-onbuild]# ls
Dockerfile-child  Dockerfile-parent
# 父镜像配置
[root@localhost dockerfile-onbuild]# vi Dockerfile-parent 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

# Install tools 
ONBUILD RUN  yum -y install telnet lrzsz iproute && yum clean all

WORKDIR /data/applog/

CMD ["/bin/bash"]

# 子镜像配置
[root@localhost dockerfile-onbuild]# vi Dockerfile-child 

# Base image
FROM rocky-onbuild

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

WORKDIR /data/applog/

CMD ["/bin/bash"]

制作镜像:

复制代码
[root@localhost dockerfile-onbuild]# docker build -t rocky-onbuild -f Dockerfile-parent .
[root@localhost dockerfile-onbuild]# docker run -d rocky-onbuild
[root@localhost dockerfile-onbuild]# docker run -it rocky-onbuild bash
[root@9d86ad43bfd2 applog]# telnet
bash: telnet: command not found

[root@localhost dockerfile-onbuild]# d​ocker build -t rocky-child -f Dockerfile-child .
[root@localhost dockerfile-onbuild]# docker run -it rocky-child bash
[root@3774c819533f applog]# telnet
telnet> 

(11)STOPSIGNAL

  • 指定容器接收退出的信号值

配置文件:

复制代码
[root@localhost dockerfile-stopsignal]# pwd
/root/dockerfile-example/dockerfile-stopsignal
[root@localhost dockerfile-stopsignal]# ls
Dockerfile  nginx.repo
[root@localhost dockerfile-stopsignal]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

ENV NGINX_VERSION=1.26.1

STOPSIGNAL SIGTERM

EXPOSE 80

# Add nginx yum repo
COPY nginx.repo /etc/yum.repos.d/nginx.repo

# Install nginx
RUN  yum -y install nginx-1:$NGINX_VERSION-1.el9.ngx.x86_64 && yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

# Start nginx daemon
CMD ["/usr/sbin/nginx"]

制作镜像:

复制代码
[root@localhost dockerfile-stopsignal]# docker build -t nginx-signal .

测试:

复制代码
[root@localhost dockerfile-stopsignal]# docker run -d --name nginx-01 nginx-signal
659d55e6d3fd91faa353113f296854592258fc3ad1410e23910bedb14f722b41
[root@localhost dockerfile-stopsignal]# docker run -d --name nginx-02 nginx-signal
e4cb66a30510593d4a22bbabe2755f8f1271b319ddf8ca05727c915b260f2003
[root@localhost dockerfile-stopsignal]# docker ps 
CONTAINER ID   IMAGE              COMMAND                   CREATED          STATUS          PORTS     NAMES
e4cb66a30510   nginx-signal       "/usr/sbin/nginx"         13 seconds ago   Up 12 seconds   80/tcp    nginx-02
659d55e6d3fd   nginx-signal       "/usr/sbin/nginx"         17 seconds ago   Up 16 seconds   80/tcp    nginx-01

[root@localhost dockerfile-stopsignal]# docker stop nginx-01
nginx-01
[root@localhost dockerfile-stopsignal]# docker inspect -f '{{.State.ExitCode}}' nginx-01
0
[root@localhost dockerfile-stopsignal]# docker kill nginx-02
nginx-02
[root@localhost dockerfile-stopsignal]# docker inspect  -f '{{.State.ExitCode}}' nginx-02
137

(12)HEALTHCHECK

  • 配置所启动容器如何进行健康检查(如何判断健康与否),自Docker 1.12开始支持。
  • 有两种格式:
  1. HEALTHCHECK [OPTIONS] CMD command:根据所执行命令返回值是否为 0 来判断;

  2. HEALTHCHECK NONE:禁止基础镜像中的健康检查

OPTION支持如下参数:

复制代码
 --ATION (default: 30s):过多久检查一次;
 --timeout=DURATION (default: 30s):每次检查等待结果的超时;
 --retries=N (default: 3):如果失败了,重试几次才最终确定失败。

配置文件:

复制代码
[root@localhost dockerfile-healthcheck]# ls
Dockerfile  http-demo
[root@localhost dockerfile-healthcheck]# vi Dockerfile 

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

WORKDIR /usr/local/app
COPY http-demo .

HEALTHCHECK --interval=30s --timeout=3s --retries=3\
  CMD curl -fs http://localhost:8080/

CMD ["./http-demo"]

制作镜像:

复制代码
[root@localhost dockerfile-healthcheck]# docker build -t http-good .

测试:

复制代码
[root@localhost dockerfile-healthcheck]# docker run -d http-good
c6b787942f3df40ec7fe34f3c51511c6129af60d3190c67764ac1b0efc64d7f3
[root@localhost dockerfile-healthcheck]# docker ps
CONTAINER ID   IMAGE              COMMAND                   CREATED          STATUS                             PORTS     NAMES
c6b787942f3d   http-good          "./http-demo"             19 seconds ago   Up 18 seconds (health: starting)             strange_archimedes
# 等待一点时间后重新查看STATUS
[root@localhost dockerfile-healthcheck]# docker ps
CONTAINER ID   IMAGE              COMMAND                   CREATED              STATUS                        PORTS     NAMES
c6b787942f3d   http-good          "./http-demo"             About a minute ago   Up About a minute (healthy)             strange_archimedes

异常示例------

配置文件:

复制代码
[root@localhost dockerfile-healthcheck]# vi Dockerfile-bad

# Base image
FROM rockylinux:9

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

WORKDIR /usr/local/app
COPY http-demo . 

HEALTHCHECK --interval=10s --timeout=1s --retries=1\
  CMD curl -fs http://localhost:8081/ 

CMD ["./http-demo"]

制作镜像:

复制代码
[root@localhost dockerfile-healthcheck]# docker build -t http-bad -f Dockerfile-bad .

测试:

复制代码
[root@localhost dockerfile-healthcheck]# docker run -d  http-bad
ef015b2eb4b04b0d4e4f18bb5ad538be12a10473bebec136d86da6c6be5a2e26
[root@localhost dockerfile-healthcheck]# docker ps
CONTAINER ID   IMAGE              COMMAND                   CREATED         STATUS                            PORTS     NAMES
ef015b2eb4b0   http-bad           "./http-demo"             5 seconds ago   Up 5 seconds (health: starting)             happy_kowalevski
# 过一会儿后再次检查STATUS
[root@localhost dockerfile-healthcheck]# docker ps
CONTAINER ID   IMAGE              COMMAND                   CREATED          STATUS                      PORTS     NAMES
ef015b2eb4b0   http-bad           "./http-demo"             21 seconds ago   Up 20 seconds (unhealthy)             happy_kowalevski

(13)SHELL

  • 指定其他命令使用 shell 时的默认shell类型:
  • SHELL ["executable", "parameters"]
  • 默认值为["/bin/sh", "-c"]

(14)RUN

  • 运行指定命令。
  • 格式为
  1. RUN <command> 在 shell 终端中执行

  2. RUN ["executable", "param1", "param2"] 使用 exec 执行

  • 每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长时可以使用 \ 来换行

例如:

复制代码
RUN  dnf -y install telnet lrzsz iproute \
                    && dnf clean all  

(15)CMD

  • CMD 指令用来指定启动容器时默认执行的命令。
  • 支持三种格式:
  1. CMD ["executable", "param1", "param2"]:相当于执行 executable param1 param2,推荐方式

  2. CMD command param1 param2:在默认的 Shell 中执行,提供给需要交互的应用;

  3. CMD ["param1", "param2"]:提供给 ENTRYPOINT 的默认参数。

  • 每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
  • 如果用户启动容器时候手动指定了运行的命令(作为 run 命令的参数),则会覆盖掉 CMD 指定的命令

CMD 与 ENTRYPOINT 的区别:

  • 相同点:ENTRYPOINT 目的和 CMD 一样,都是指定容器启动程序及参数。
  • 不同点:当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,实际执行时,将变为:<ENTRYPOINT> "<CMD>"

(16)ADD

  • 添加内容到镜像。
  • 格式为 ADD <src> <dest>
  • 该命令将复制指定的 <src> 路径下内容到容器中的 <dest> 路径下。
  • 其中 <src> 可以是 Dockerfile 所在目录的一个相对路径(文件或目录);也可以是一个 URL;还可以是一个tar 文件(自动解压为目录)<dest> 可以是镜像内绝对路径,或者相对于工作目录(WORKDIR)的相对路径

配置文件:

复制代码
[root@localhost dockerfile-example]# cd dockerfile-add/
[root@localhost dockerfile-add]# ls
Dockerfile-v1  Dockerfile-v2  Dockerfile-v3  nginx-1.22.1  nginx-1.22.1.tar.gz
[root@localhost dockerfile-add]# vi Dockerfile-v1

# Base image
FROM rockylinux:9 

# Maintainer
LABEL authors="chijinjing@xinxianghf.com"

# Add directory
ADD nginx-1.22.1 /usr/local/src/nginx-1.22.1
# 添加远程文件到容器内
# ADD  https://nginx.org/download/nginx-1.22.1.tar.gz  /usr/local/src
# 添加压缩文件到容器内
# ADD  nginx-1.22.1.tar.gz  /usr/local/src

CMD ["/bin/bash"]

制作镜像:

复制代码
[root@localhost dockerfile-add]# docker build -t add:v1 -f Dockerfile-v1  .
[root@localhost dockerfile-add]# docker run --rm add:v1 ls /usr/local/src
nginx-1.22.1

(17)COPY

  • 复制内容到镜像。
  • 格式为 COPY <src> <dest>
  • 复制本地主机的 <src>(为Dockerfile所在目录的相对路径,文件或目录)下内容到镜像中的 <dest>。目标路径不存在时,会自动创建。
  • 路径同样支持正则格式

COPY&&ADD

  • COPY 的语义很明确,就是复制文件而已
  • ADD 则包含了更复杂的功能,其行为也不一定很清晰
  • 最适合使用 ADD 的场合,就是需要自动解压缩的场合
相关推荐
安审若无2 小时前
图数据库neoj4安装部署使用
linux·运维·数据库
做运维的阿瑞3 小时前
CentOS DNS故障排查完整解决方案:从症状到根因的系统化诊断
linux·运维·centos
武子康4 小时前
Java-166 Neo4j 安装与最小闭环 | 10 分钟跑通 + 远程访问 Docker neo4j.conf
java·数据库·sql·docker·系统架构·nosql·neo4j
深圳市恒讯科技4 小时前
英国服务器Windows系统远程桌面安装与优化
运维·服务器·windows
itachi-uchiha4 小时前
head和tail命令使用
linux·运维·服务器
violet-lz4 小时前
Socket编程实战:从基础API到多线程服务器
运维·服务器
初学者_xuan4 小时前
零基础新手小白快速了解掌握服务集群与自动化运维(十六)集群部署模块——LVS-DR&TUN模式配置
运维·自动化·lvs
toooooop84 小时前
Nginx 反向代理 HTTPS CDN 配置检查清单(避坑版)
运维·nginx·https·cdn
群联云防护小杜4 小时前
国产化环境下 Web 应用如何满足等保 2.0?从 Nginx 配置到 AI 防护实战
运维·前端·nginx