# 04.Docker镜像制作 ## 04.Docker镜像制作 ### 1. Docker镜像制作 ### 2. 基于rocky手动构建nginx镜像 Docker镜像制作类似于虚拟机的模板制作,即按照公司的实际业务将需要安装的软件、相关配置等基础环境配置完成,然后将容器再提交为模板,最后再批量从模板批量创建新的虚拟机,这样可以极大地简化业务中相同环境的虚拟机运行环境的部署工作,Docker的镜像制作分为手动制作可自动制作(基于DockerFile),企业通常都是基于DockerFile制作镜像。 #### 2.1 从初始镜像开始构建 一、启动一个RockyLinux容器,安装好nginx以及常用软件 ```bash [root@localhost ~]# docker run -it -d --name mynginx_server rockylinux:9 bash 18914b0f6005e7b20122508f8bc70a830845711ff6200392bf0a7c76dc4a8a60 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 18914b0f6005 rockylinux:9 "bash" 3 seconds ago Up 2 seconds mynginx_server [root@localhost ~]# docker exec -it mynginx_server bash # 进入容器以后,安装nginx以及一些常用的软件 [root@18914b0f6005 /]# yum install -y epel-release nginx [root@18914b0f6005 /]# yum install vim wget pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop -y ``` 二、关闭nginx后台运行 ```bash [root@18914b0f6005 /]# vim /etc/nginx/nginx.conf ...... daemon off; ...... ``` 三、自定义web界面 ```bash [root@18914b0f6005 /]# vim /etc/nginx/nginx.conf [root@18914b0f6005 /]# echo "

Welcome to Eagle nginx...

" > /usr/share/nginx/html/index.html ``` #### 2.2 镜像提交 通过commit提交为镜像 ```bash [root@localhost ~]# docker commit --help Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] Create a new image from a container's changes Aliases: docker container commit, docker commit Options: -a, --author string Author (e.g., "John Hannibal Smith ") -c, --change list Apply Dockerfile instruction to the created image -m, --message string Commit message -p, --pause Pause container during commit (default true) # 重新打包为新镜像 [root@localhost ~]# docker commit -a "Eagle_nls" -m "my nginx image v1" 18914b0f6005 rocky_nginx:v1 sha256:9411e13b57d003a6d709054ccbbc026a7b005a1727ec470755f987e25ff45a6b [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE rocky_nginx v1 9411e13b57d0 33 seconds ago 357MB mynginx v1 81ef4ae01fed 2 hours ago 190MB codercom/code-server latest 5d9cf2e7e6bb 10 days ago 718MB neosmemo/memos latest 8f07b54db502 6 weeks ago 65.9MB ``` docker commit**适用场景:**主要作用是将配置好的一些容器复用,再生成新的镜像。 commit是合并了save、load、export、import这几个特性的一个综合性的命令,它主要做了: 1、将container当前的读写层保存下来,保存成一个新层 2、和镜像的历史层一起合并成一个新的镜像 #### 2.3 从新镜像启动容器 从自己的镜像启动容器 ```bash [root@localhost ~]# docker run -d -p 80:80 --name mynginx_rocky rocky_nginx:v1 /usr/sbin/nginx dc4225c68d28ffdcc559662b8680f9e4b4b95bdaeeca2f1ed566d638aa8fc8fe [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dc4225c68d28 rocky_nginx:v1 "/usr/sbin/nginx" 2 seconds ago Up 1 second 0.0.0.0:80->80/tcp, [::]:80->80/tcp mynginx_rocky ``` 访问测试: ![image-20250325185125851](04.Docker镜像制作/image-20250325185125851.png) ### 3. DockerFile制作镜像 Dockerfile 是一种可以被 Docker 程序解释的脚本,它是一个文本文件,包含了一系列指令,用于定义如何构建 Docker 镜像。每一条指令都会创建镜像的一层,最终生成的镜像是由这些层叠加而成的。Dockerfile 中的指令关键字必须大写,执行顺序是从上到下,且每条指令创建一个镜像层。 Docker 程序会读取 Dockerfile 并根据指令生成 Docker 镜像。Dockerfile 的指令类似于 Linux 下的命令,但 Docker 程序会将这些 Dockerfile 指令翻译成真正的 Linux 命令来执行。相比手动制作镜像的方式,Dockerfile 能更直观地展示镜像是如何产生的。有了写好的 Dockerfile 文件,当后期某个镜像有额外的需求时,只需在之前的 Dockerfile 中添加或修改相应的操作,即可重新生成新的 Docker 镜像,避免了重复手动制作镜像的麻烦。 #### 3.1 指令说明 ##### 3.1.1 配置指令 | 指令 | 说明 | | :------------ | :--------------------------------- | | `ARG` | 定义创建镜像过程中使用的变量 | | `FROM` | 指定所创建镜像的基础镜像 | | `LABEL` | 为生成的镜像添加元数据标签信息 | | `EXPOSE` | 声明镜像内服务监听的端口 | | `ENV` | 指定环境变量 | | `ENTRYPOINT` | 指定镜像的默认入口命令 | | `VOLUME` | 创建一个数据卷挂载点 | | `USER` | 指定运行容器时的用户名或UID | | `WORKDIR` | 配置工作目录 | | `ONBUILD` | 创建子镜像时指定自动执行的操作指令 | | `STOPSIGNAL` | 指定退出的信号值 | | `HEALTHCHECK` | 配置所启动容器如何进行健康检查 | | `SHELL` | 指定默认shell类型 | ##### 3.1.2 操作指令 | 指令 | 说明 | | :----- | :--------------------------- | | `RUN` | 运行指定命令 | | `CMD` | 启动容器时指定默认执行的命令 | | `ADD` | 添加内容到镜像 | | `COPY` | 复制内容到镜像 | #### 3.2 配置指令详解 ##### 3.2.1 ARG 定义创建过程中使用到的变量,例如 `HTTP_PROXY`、`HTTPS_PROXY`、`FTP_PROXY`、`NO_PROXY` 等,不区分大小写。 ##### 3.2.2 FROM 指定所创建镜像的基础镜像。为了保证镜像精简,可以选用体积较小的 Alpin 或 Debian 作为基础镜像。 ##### 3.2.3 EXPOSE 声明镜像内服务监听的端口。例如: ```bash EXPOSE 22 80 8443 ``` 该指令只是起到声明作用,并不会自动完成端口映射。 ##### 3.2.4 ENTRYPOINT 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。支持两种格式: - `ENTRYPOINT ["executable","param1","param2"]`(exec 调用执行) - `ENTRYPOINT command param1 param2`(在 shell 中执行) 此时 `CMD` 指令指定值将作为根命令的参数。每个 Dockerfile 中只能有一个 `ENTRYPOINT`,当指定多个时只有最后一个起效。 ##### 3.2.5 VOLUME 创建一个数据卷挂载点。例如: ```bash VOLUME ["/data"] ``` ##### 3.2.6 WORKDIR 为后续的 `RUN`、`CMD`、`ENTRYPOINT` 指令配置工作目录。例如: ```bash WORKDIR /path/to/workdir ``` 可以使用多个 `WORKDIR` 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如: ```bash WORKDIR /a WORKDIR b WORKDIR c RUN pwd ``` 最终路径为 `/a/b/c`。因此,为了避免出错,推荐在 `WORKDIR` 指令中只使用绝对路径。 ##### 3.2.7 操作指令详解 ##### 3.2.8 RUN 运行指定Linux命令。每条 `RUN` 指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长时可以使用 `\` 来换行。 ##### 3.2.9 CMD `CMD` 指令用来指定启动容器时默认执行的命令。支持三种格式: - `CMD ["executable","param1","param2"]`(相当于执行 `executable param1 param2`) - `CMD command param1 param2`(在默认的 shell 中执行,提供给需要交互的应用) - `CMD ["param1","param2"]`(提供给 `ENTRYPOINT` 的默认参数) 每个 Dockerfile 只能有一条 `CMD` 命令。如果指定了多条命令,只有最后一条会被执行。 ##### 3.2.10 ADD 添加内容到镜像。例如: ```bash ADD ``` 该命令将复制指定的 `src` 路径下内容到容器中的 `dest` 路径下。`src` 可以是 Dockerfile 所在目录的一个相对路径,也可以是一个 URL,还可以是一个 tar 文件。`dest` 可以是镜像内绝对路径,或者相对于工作目录的相对路径。 ##### 3.2.11 COPY 复制内容到镜像。例如: ```bash COPY ``` `COPY` 与 `ADD` 指令功能类似,当使用本地目录为源目录时,推荐使用 `COPY`。 #### 3.3 制作nginx镜像 DockerFile可以说是一种可以被Docker程序解释的脚本,DockerFIle是由一条条的命令组成的,每条命令对应Linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的Linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像。 ##### 3.3.1 基于编译安装制作nginx小游戏网站 ###### 3.3.1.1 环境准备 一、下载镜像 ```bash [root@localhost ~]# docker pull rockylinux:9 ``` 二、创建所需文件存放的目录环境 ```bash [root@localhost ~]# mkdir -pv dockerfile/nginx mkdir: created directory 'dockerfile' mkdir: created directory 'dockerfile/nginx' ``` 三、进入到指定目录中 ```bash [root@localhost ~]# cd dockerfile/nginx/ [root@localhost nginx]# pwd /root/dockerfile/nginx ``` 四、下载nginx和小游戏网页的源码包 ```bash [root@localhost nginx]# wget http://nginx.org/download/nginx-1.22.0.tar.gz [root@localhost nginx]# wget http://file.eagleslab.com:8889/%E8%AF%BE%E7%A8%8B%E7%9B%B8%E5%85%B3%E8%BD%AF%E4%BB%B6/%E4%BA%91%E8%AE%A1%E7%AE%97%E8%AF%BE%E7%A8%8B/%E8%AF%BE%E7%A8%8B%E7%9B%B8%E5%85%B3%E6%96%87%E4%BB%B6/games.tar.gz [root@localhost nginx]# ll total 125100 -rw-r--r--. 1 root root 127022187 Jan 18 2022 games.tar.gz -rw-r--r--. 1 root root 1073322 May 24 2022 nginx-1.22.0.tar.gz ``` ###### 3.3.1.2 编写Dockerfile 一、编写DockerFile ```bash [root@docker-server nginx]# vim Dockerfile # 第一行先定义基础镜像,后面的本地有效的镜像名,如果本地没有,会从远程仓库下载 FROM rockylinux:9 # 镜像作者的信息 MAINTAINER Eagle_nls 2898485992@qq.com # 接下来在基础镜像之上构建nginx等所需环境 # 1. 编译安装nginx # 1.1 安装所需环境及工具 RUN yum install -y vim wget unzip tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop # 1.2 上传nginx的官方源码包到指定目录 ADD nginx-1.22.0.tar.gz /usr/local/src/ # 1.3 由于ADD会直接解压好,所以直接编译nginx RUN cd /usr/local/src/nginx-1.22.0 \ && ./configure --prefix=/usr/local/nginx --with-http_sub_module \ && make \ && make install \ && cd /usr/local/nginx # 如果有配置文件,可以上传自己准备好的配置文件 # ADD nginx.conf /usr/local/nginx/conf/nginx.conf # 2. 完善网站 RUN useradd -s /sbin/nologin nginx \ && ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx # 3. 上传小游戏网页源码 ADD games.tar.gz /usr/local/nginx/html/ # 4. 声明端口号 EXPOSE 80 443 # 5. 设定启动时执行命令 CMD ["nginx", "-g", "daemon off;"] ``` ###### 3.3.1.3 构建镜像 一、通过docker build来构建镜像 ```bash [root@localhost nginx]# docker build -t nginx_games:v1 . [root@localhost nginx]# docker images |grep nginx_games nginx_games v1 9c86d96dfba0 4 minutes ago 686MB ``` 二、镜像运行测试 ```bash [root@localhost nginx]# docker run -d -it -p 80:80 --name nginx_games nginx_games:v1 e3c415425f95b3deac80ecb772d1de2a89e18a611c2ecc603f3c0b175bbea335 [root@localhost nginx]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e3c415425f95 nginx_games:v1 "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 443/tcp nginx_games ``` 三、访问测试 ![image-20250325195752895](04.Docker镜像制作/image-20250325195752895.png) ### 4. 镜像上传 #### 4.1 官方docker仓库 - 准备账户 登陆到docker hub官网创建账号,登陆后点击settings完善信息 - 填写账户基本信息 ![image-20220920090601269](04.Docker镜像制作/image-20220920090601269.png) - 登陆仓库 ```bash [root@docker-server ~]# docker login docker.io Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: smqy 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/#credentials-store Login Succeeded [root@docker-server ~]# ls -a . .bash_history .bashrc dockerfile .tcshrc .. .bash_logout .cshrc docker_in.sh .viminfo anaconda-ks.cfg .bash_profile .docker .pki [root@docker-server ~]# cat .docker/config.json { "auths": { "https://index.docker.io/v1/": { "auth": "YmJqMTAzMDp6aGFuZ2ppZTEyMw==" } } }[root@docker-server ~]# ``` - 给镜像tag标签并上传 ```bash [root@docker-server ~]# docker tag nginx:v1 docker.io/smqy/nginx:v1 [root@docker-server ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx v1 fbd06c1753c0 12 minutes ago 581MB smqy/nginx v1 fbd06c1753c0 12 minutes ago 581MB centos_nginx v1 74acdcca8c97 21 hours ago 525MB nginx latest 2b7d6430f78d 3 weeks ago 142MB centos 7 eeb6ee3f44bd 12 months ago 204MB nginx 1.8 0d493297b409 6 years ago 133MB [root@docker-server ~]# docker push docker.io/smqy/nginx:v1 The push refers to repository [docker.io/smqy/nginx] 4f86a3bf507f: Pushed 0d11c01ff3ef: Pushed 45fc5772a4e4: Pushed 174f56854903: Mounted from library/centos v1: digest: sha256:385bfe364839b645f1b2aa70a1d779b0dca50256ea01ccbe4ebde53aabd1d96d size: 1164 ``` - 到docker官网进行验证 ![image-20220920091110123](04.Docker镜像制作/image-20220920091110123.png) - 更换到其他docker服务器下载镜像 ```bash [root@docker-server ~]# docker login docker.io ``` #### 4.2 阿里云仓库 将本地镜像上传至阿里云,实现镜像备份与统一分发的功能 https://cr.console.aliyun.com/ 注册并且登录阿里云镜像仓库,创建namespace空间,创建一个普通的镜像仓库 ![image-20250325201301197](04.Docker镜像制作/image-20250325201301197.png) 具体如何拉取镜像,上传镜像,可以查看阿里云仓库下方提供的操作指南 ##### 4.2.1 Push镜像案例 一、登录阿里云仓库 ```bash [root@localhost nginx]# docker login --username=Echooool registry.cn-hangzhou.aliyuncs.com i Info → A Personal Access Token (PAT) can be used instead. To create a PAT, visit https://app.docker.com/settings Password: Error response from daemon: Get "https://registry.cn-hangzhou.aliyuncs.com/v2/": unauthorized: authentication required [root@localhost nginx]# docker login --username=Echooool registry.cn-hangzhou.aliyuncs.com i Info → A Personal Access Token (PAT) can be used instead. To create a PAT, visit https://app.docker.com/settings Password: WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'. Configure a credential helper to remove this warning. See https://docs.docker.com/go/credential-store/ Login Succeeded ``` 二、推送镜像 ```bash # 先给要推送的镜像打上标签 [root@localhost nginx]# docker tag 9c86d96dfba0 registry.cn-hangzhou.aliyuncs.com/atopos/docker_hub:nginx_games-v1 # 推送镜像 docker push registry.cn-hangzhou.aliyuncs.com/atopos/docker_hub:nginx_games-v1 ``` 三、阿里云查看 ![image-20250325202050140](04.Docker镜像制作/image-20250325202050140.png) 四、拉取镜像 ```bash [root@localhost nginx]# docker pull registry.cn-hangzhou.aliyuncs.com/atopos/docker_hub:nginx_games-v1 nginx_games-v1: Pulling from atopos/docker_hub 446f83f14b23: Already exists d9262d5a1401: Already exists 7330c5b74c49: Already exists 55e1c23f0b49: Already exists 5de772a29709: Already exists f4819c5e7596: Already exists Digest: sha256:f9a6ac50b9771c524017304847f3d8b2ffa4acbe01cef9279052272e50a9a3f3 ```