Docker容器实践——使用Dockerfile构建docker镜像

Docker容器实践------私有镜像仓库(Harbor)的使用https://coffeemilk.blog.csdn.net/article/details/160312595

一、使用Dockerfile定制镜像

1.1、Dockerfile是什么

镜像是分层构建的,那要定制镜像,实际上就是定制每一层所添加的配置和文件。若可以把每一层的修改、安装、构建、操作命令都写入一个脚本,然后在用这个脚本来构建定制镜像,那么就可以实现自动化、快速制作定制的镜像了;同时镜像中透明性的问题、体积问题也会得到解决,这个脚本就是Dockerfile。

Dockerfile是一个文本文件(其内包含了一条条指令【Instruction】,每条指令构建一层,因此每一条指令的内容,就是描述该层应该如何构建)。有了Dockerfile当我们需要定制自己额外的需求时,只需要在Dockerfile上添加或修改指令后,重新生成镜像即可,同时省去了一行行敲命令的麻烦。

1.2、简单的Dockerfile文件

bash 复制代码
#使用简单的Dockerfile文件构建镜像
#1-创建指定目录并进入
mkdir -p /data/imagestest
cd /data/imagestest

#2-创建Dockerfile文件
touch Dockerfile
vi Dockerfile
#【Dockerfile】文件的内容
FROM nginx:1.28.3
RUN echo "<h1>Hello Docker!</h1>" >/usr/share/nginx/html/index.html

#3-使用Dockerfile文件构建镜像命令
#注意:若Dockerfile文件名称不是Dockerfile而是其他的名称,则需要使用【-f dockerfile文件名称】(如:docker build -t nginx:v-1.28.3 -f dockerfile2 .)最后的点表示在当前目录
docker build -t nginx:v-1.28.3 .

#4-查看所有的镜像
docker images

#5-运行刚构建好的镜像
docker run -itd -p 8001:80 nginx:v-1.28.3

#6-在浏览器访问【IP:8001】可以看到结果显示"Hello Docker!"

二、 Dockerfile的常见指令与构建镜像原理

2.1、Dockerfile的常见指令解析

Dockerfile共分为四个部分:【基础镜像信息】【维护者信息】【镜像操作指令】【容器启动指令】

Dockerfile常见指令 说明
FROM <image> **【指定基础镜像】**必须是第一条指令 还可使用【FROM ... AS builder】多阶段构建机制,通过在单个Dockerfile中定义多个构建阶段来实现;每个阶段可以使用不同的基础镜像,并且可以选择性的仅从某个阶段中复制文件到最终镜像中,这种方法可以减少最终镜像的大小。
RUN <command> **【执行命令行命令】**是在定制镜像时常用命令之一,有两种格式: 《1》shell格式:RUN <命令> 《2》exec格式:RUN ["可执行文件","参数1","参数2",...]
WORKDIR <directory> 【设置容器内的工作目录】 在构建和运行容器时,所有后续的命令(如:RUN、CMD、ENTRYPOINT等)都将在这个工作目录中执行。 若该目录不存在,WORKDIR会帮你自动创建目录。
COPY [--chown=<user>:<group>] <src> <dest> 【复制文件或目录到正在构建的镜像中指定位置】 * -chown=<user>:<group>:是可选参数,用于指定复制到镜像中文件的所有者和所属组;若未指定该参数,则保留文件原始所有者和所属组。 * <src>:要复制到镜像的文件或目录在宿主机上的路径,可指定多个源路径,可使用通配符。 * <dest>:在镜像内部文件系统中的目标路径,指定文件或目录被复制到该位置。
ADD <src> <dest> 【用于将文件或目录从构建上下文(构建环境)添加到镜像中】 ADD指令的作用类似与COPY指令,但也有差异(除了复制文件外,ADD指令还可以执行额外的功能【如:自动解压缩tar文件和URL下载等】)。 若源路径是一个tar压缩文件,压缩格式为gzip、bzip2或xz的情况,则ADD指定会自动解压缩这个文件到<目标路径>中。
VOLUME ["<路径1>","<路径2>",...] **【指定容器中哪些目录下的数据应该保存到宿主机中】**而不受容器的生命周期影响(即:在容器创建的时候,Docker会自动为这些挂载点创建匿名数据卷)
CMD ["可执行文件","参数1","参数2",...] 【设置容器启动时默认要执行的命令】 每个Docker镜像中建议有一个CMD指令,它定义了在容器启动时运行的默认命令;若在Dockerfile中使用多个CMD指令,只有最后一个指令会生效。CMD指令与RUN指令相似,也有两种格式: 《1》shell格式:CMD <命令> 《2》exec格式:["可执行文件","参数1","参数2",...] 在指令格式上,一般推荐使用exec格式,这类格式在解析时会被解析为JSON数组,因此一定要使用双引号,不要使用单引号。
ENTRYPOINT ["<可执行文件>", "<参数1>", "<参数2>", ...] **【配置容器启动时的默认可执行程序】**它会在容器启动时始终运行,而不会被覆盖。 与CMD指令不同,ENTRYPOINT 指令不会被docker run命令行中的命令覆盖,而是始终作为容器的入口点执行。 ENTRYPOINT指令的语法有两种格式: 《1》shell格式:ENTRYPOINT <命令>。 《2》exec 格式:ENTRYPOINT ["<可执行文件>", "<参数1>", "<参数2>", ...]。 注意:ENTRYPOINT 指令还还可以与CMD指令一起使用,以指定默认参数。在这种情况下,CMD提供的参数将成为ENTRYPOINT指定的可执行文件的参数。
EXPOSE <端口1> [<端口2> <端口3> ...] 【用于声明容器在运行时将监听的端口】 注意:EXPOSE 仅仅是一个声明,它不会在宿主机上打开或映射端口。它只是在构建镜像时提供了关于容器中监听的端口信息。在运行容器时,我们仍然需要使用 -p 或 -P 选项来将容器内部的端口映射到主机上。
USER <用户名>[:<用户组>] 【设置在容器内部运行后续命令的默认用户】 通常,Docker容器在默认情况下以root用户权限运行,但为了安全性和最小权限原则,我们可以使用USER指令来切换到非特权用户。 其中 <用户名> 是要切换到的用户的用户名,<用户组> 是可选的用户组。
ENV <键>=<值> ... 【设置环境变量】 环境变量是在容器运行时可用的键值对,可以在容器内的各个进程中使用。 其中 <键> 是环境变量的名称,<值> 是与之相关联的值。 注意:这里设置的键对应的值,可以在运行容器的时候,使用【-e】参数指定自己想要的内容覆盖。

2.2、docker build的工作原理

Docker在运行时分为【Docker 引擎】(也就是服务端守护进程)和【客户端工具】。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。

当进行镜像构建的时候,并非所有定制都会通过RUN指令完成,经常会需要将一些本地文件复制进镜像(如:通过 COPY 指令、ADD指令等)。而 docker build命令构建镜像,其实并非在本地构建,而是在服务端,也就是Docker引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?(这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build命令得知这个路径后,会将路径下的所有内容打包,然后上传给Docker引擎。这样Docker引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件)。

实际上Dockerfile的文件名并不要求必须为Dockerfile,而且并不要求必须位于上下文目录中(如:可以用-f参数指定某个文件作为Dockerfile),当然,一般大家习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中。

三、使用Dockerfile构建镜像示例

编写Nginx镜像的Dockerfile:

bash 复制代码
#编写Nginx镜像的Dockerfile
mkdir -p /data/imagestest/nginx
cd /data/imagestest/nginx
vi Dockerfile


#【Dockerfile】文件的完整内容
# 使用官方almalinux9.2作为基础镜像(编译阶段)
FROM almalinux/9-base:9.2 AS builder

MAINTAINER coffeemilk@ck.com

# 安装编译依赖
RUN yum install -y wget make autoconf openssl openssl-devel crontabs \
    libxslt-devel gd gd-devel pcre pcre-devel zlib zlib-devel \
    gcc gcc-c++ glibc && \
    yum clean all && rm -rf /var/cache/yum

# 创建www运行用户
RUN useradd -M -s /sbin/nologin www

# 工作目录
WORKDIR /usr/local/src

# 下载并解压Nginx
ENV NGINX_VERSION=1.30.0
RUN wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && \
    tar -zxvf nginx-${NGINX_VERSION}.tar.gz

# 编译安装Nginx
WORKDIR /usr/local/src/nginx-${NGINX_VERSION}
RUN ./configure \
    --user=www \
    --group=www \
    --prefix=/usr/local/nginx \
    --with-file-aio \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_xslt_module \
    --with-http_image_filter_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_auth_request_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_degradation_module \
    --with-http_stub_status_module \
    && make -j$(nproc) \
    && make install

# ====================== 最终运行镜像 ======================
FROM almalinux/9-base:9.2

MAINTAINER coffeemilk@ck.com

# 安装Nginx运行时依赖(必须安装,否则无法启动)
RUN yum install -y openssl libxslt gd pcre zlib && \
    yum clean all && rm -rf /var/cache/yum

# 创建运行用户
RUN useradd -M -s /sbin/nologin www

# 从编译阶段复制Nginx程序
COPY --from=builder /usr/local/nginx /usr/local/nginx

# 复制配置文件(宿主机文件)
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
COPY fastcgi_params /usr/local/nginx/conf/fastcgi_params
RUN mkdir -p /usr/local/nginx/conf/conf.d
COPY www.conf /usr/local/nginx/conf/conf.d/www.conf

# 自定义首页
RUN echo "This is Coffeemilk DockerWebserver for Nginx" > /usr/local/nginx/html/index.html

# 环境变量
ENV PATH="/usr/local/nginx/sbin:$PATH"

# 暴露端口
EXPOSE 80

# 前台启动Nginx
CMD ["nginx", "-g", "daemon off;"]
bash 复制代码
#配套的最小化配置文件
#【nginx.conf】(Nginx主配置)文件内容
user  www;
worker_processes  auto;

#日志/进程ID路径 匹配编译安装目录
error_log  /usr/local/nginx/logs/error.log warn;
pid        /usr/local/nginx/logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /usr/local/nginx/logs/access.log  main;

    sendfile        on;
    keepalive_timeout  65;

    # 加载子配置
    include /usr/local/nginx/conf/conf.d/*.conf;
}
bash 复制代码
#配套的最小配置文件
#【fastcgi_params】(Nginx默认文件)文件内容
fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

fastcgi_param  REDIRECT_STATUS    200;
bash 复制代码
#配套的最小化配置文件
#【www.conf】(站点配置)文件内容
server {
    listen       80;
    server_name  localhost;

    root   /usr/local/nginx/html;
    index  index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page  404  /404.html;
    error_page  500 502 503 504  /50x.html;
}
bash 复制代码
#1-在宿主机的目录下创建【nginx.conf(主配置)、fastcgi_params(Nginx 默认文件)、conf.d/www.conf(站点配置)、Dockerfile四个文件】
cd /data/imagestest/nginx
ll

#2-构建Nginx镜像
docker build -t nginx:ck-1.30.0 .

#3-运行容器
docker run -d --name nginx-web -p 8002:80 nginx:ck-1.30.0

#4-在浏览器访问【ip:8002】若界面显示"This is Coffeemilk DockerWebserver for Nginx"则构建成功

#5-查看日志(确认无报错)
docker logs nginx-web
相关推荐
小夏子_riotous2 小时前
Docker学习路径——4、制作/更改镜像
学习·docker
小锋学长生活大爆炸5 小时前
【教程】在Docker中部署Hermes Agent
docker·容器·agent·教程·工具·openclaw·hermes
AI服务老曹13 小时前
异构计算时代的安防底座:基于 Docker 的 X86/ARM 双模部署与 NPU 资源池化实战
arm开发·docker·容器
筱顾大牛15 小时前
使用docker部署到服务器
docker·部署
another heaven18 小时前
【Docker/虚拟机 深度对比Docker与虚拟机:原理、区别与最佳使用场景】
运维·docker·容器
独自归家的兔18 小时前
2026年4月16日 Ubuntu系统 Docker 的安装与配置
运维·docker·容器
舒一笑19 小时前
Docker 离线镜像导入后变成 <none>:<none>?一文讲透原因、排查与正确打包姿势
后端·docker·容器
Bonnienienie20 小时前
服务器Docker实例化容器 -- 踩坑大全
docker
殷紫川20 小时前
Docker Compose实战指南
运维·docker