【Docker】Dockerfile自定义镜像

创建自定义的镜像有两种方法

1.命令式创建镜像--进入容器输入命令创建镜像

bash 复制代码
apk update

apk add#安装软件

将容器保存为新镜像分享commit

将容器 9aaf3cd86741 (容器id)的当前状态提交为一个新的镜像,镜像名称为 alpine-figlet。

bash 复制代码
docker commit 9aaf3cd86741 alpine-figlet

命令式创建的局限性

  1. 不可重复性:容器安装过程依赖人工操作,无法保证环境一致性
  2. 臃肿镜像:容器可能包含临时文件/缓存,导致镜像体积膨胀
  3. 安全风险:无法追溯安装过程,可能存在安全隐患
  4. 维护困难:无法版本化管理构建步骤

2.声明式创建镜像- -用dockerfile

Dockerfile

Dockerfile 是一个纯文本文件 ,用于定义如何构建 Docker 镜像。它包含了一系列指令 ,Docker 会按照这些指令的顺序自动执行 ,最终生成 一个可复用的镜像

常用指令

指令 作用 示例
FROM 指定基础镜像,是 Dockerfile 的第一个指令。 FROM ubuntu:25.04
RUN 在镜像构建过程中执行命令,用于安装软件、配置环境等。 RUN apt-get update && apt-get install -y nginx
COPY 将宿主机的文件或目录复制到镜像中。 COPY index.html /var/www/html/
ADD 类似 COPY,还支持远程文件下载、解压压缩包等。 ADD https://example.com/file.tar.gz /app/
CMD 容器启动时执行的默认命令,若镜像启动时指定了其他命令则会覆盖。 CMD ["nginx", "-g", "daemon off;"]
EXPOSE 声明容器对外暴露的端口 (仅为说明,实际端口映射需在 docker run 时指定)。 EXPOSE 80
WORKDIR 设置后续指令的工作目录,避免使用绝对路径,增强可维护性。 WORKDIR /app
ENV 设置环境变量,可在后续指令和容器运行时使用。 ENV APP_PORT=8080

dockerfile例子

bash 复制代码
#声明式构建镜像:使用 ubuntu:25.04 作为基础镜像
FROM ubuntu:25.04

#首先要更新本地软件包索引&&
#安装 nginx(Nginx是一款高性能的开源 Web 服务器、反向代理服务器和负载均衡器)
RUN apt-get update && \
    apt-get install -y nginx

#创建一个简单的 HTML 文件
RUN echo '<h1>Hello Docker!</h1>' > /tmp/index.html

#将刚刚的 HTML 文件移动到容器内的 Nginx 默认的静态网站根目录,即 `/var/www/html/`
RUN mv /tmp/index.html /var/www/html/

#暴露 80 端口
EXPOSE 80

#启动 nginx 服务
CMD ["nginx", "-g", "daemon off;"]

可以用一条 apt-get install 命令一次性安装多个软件,用空格将不同的软件名隔开即可。 例如 apt-get install -y tree python3 表示安装 treepython3

每条指令都创建并提交一个新的镜像层

使用dockerfile构建

根据当前目录下的 Dockerfile 文件,构建一个名为 alpine-figlet-from-dockerfile 的 Docker 镜像

docker build -t 依据的文件名 -f 文件位置 输出位置

bash 复制代码
docker build -t alpine-figlet-from-dockerfile .

分阶段构建

单阶段

Dockerfile.single

bash 复制代码
FROM golang:1.23

# 定义构建参数
ARG PORT=8080
# 设置环境变量
ENV PORT=${PORT}
# 指定工作目录
WORKDIR /app

#将本地的 go.mod(依赖管理文件)和 main.go(应用主代码)复制到容器的 /app 目录下。
COPY go.mod .
COPY main.go .

#禁用 CGO(Go 调用 C 代码的机制),确保编译出的程序是纯 Go 静态链接的,不依赖系统动态库。
ENV CGO_ENABLED=0
#指定目标操作系统为 Linux,确保编译出的程序能在 Linux 容器中运行。
ENV GOOS=linux

#根据go.mod整理依赖 && 编译 Go 程序
RUN go mod tidy && go build -ldflags="-w -s" -o server .

EXPOSE ${PORT}

#运行
CMD ["./server"]

多阶段

构建和执行阶段分开。

每个阶段都要设置初始镜像、环境、工作目录

执行阶段把构建阶段编译好的文件复制过来执行

  • AS 阶段名:为阶段命名(如 AS builder),方便后续通过 --from=阶段名 引用。
  • COPY --from=阶段名:从指定阶段复制文件到当前阶段(核心指令)。
bash 复制代码
# 第一阶段:构建阶段
# builder是别名
FROM golang:1.23 AS builder

# 设置工作目录
WORKDIR /app

# 将源代码复制到容器中
COPY go.mod .
COPY main.go .

# 设置必要的 Go 环境变量
ENV CGO_ENABLED=0
ENV GOOS=linux

# 编译 Go 应用
RUN go mod tidy && go build -ldflags="-w -s" -o server .


# 第二阶段:运行阶段
FROM alpine:latest

# 定义构建参数
ARG PORT=8081
# 设置环境变量
ENV PORT=${PORT}

# 安装 CA 证书,这在某些需要 HTTPS 请求的应用中可能需要
RUN apk --no-cache add ca-certificates

# 设置工作目录
WORKDIR /root/

# 从 builder 阶段复制编译好的二进制文件
COPY --from=builder /app/server .

# 暴露应用端口
EXPOSE ${PORT}

# 运行应用
CMD ["./server"]

多阶段构建的优点

  • 减小镜像体积:最终镜像仅包含运行所需的可执行文件,不包含编译工具(如 Go 编译器)和源码,体积可缩小 90% 以上。
  • 隔离构建依赖:构建阶段的依赖(如编译工具、临时文件)不会污染最终镜像,提升安全性。
  • 简化流程:无需手动编写脚本复制产物,所有步骤在一个 Dockerfile 中完成。
相关推荐
每日出拳老爷子5 小时前
【远程协助】内网 IT 运维远程协助系统的最小可用架构
运维·服务器·远程工作·流媒体·视音频
weixin_462446235 小时前
使用 Puppeteer 设置 Cookies 并实现自动化分页操作:前端实战教程
运维·前端·自动化
实战项目7 小时前
软件测试自动化框架的设计与实现
运维·自动化
Aotman_7 小时前
Element-UI Message Box弹窗 使用$confirm方法自定义模版内容,修改默认样式
linux·运维·前端
Elastic 中国社区官方博客8 小时前
使用 Elastic 中的 OpenTelemetry 为 Nginx 实现端到端分布式追踪的实用指南
大数据·运维·分布式·elasticsearch·搜索引擎·信息可视化·全文检索
独自破碎E8 小时前
配置ssh解决https不稳定的问题
运维·ssh
那些年的笔记9 小时前
Linux屏幕旋转方法
linux·运维·服务器
竹之却9 小时前
CentOS 系列,防火墙相关指令
linux·运维·centos
JadenOliver9 小时前
Docker 守护进程核心配置入口:daemon.json
docker·daemon.json
gaize12139 小时前
科普篇“机架、塔式、刀片”三类服务器对比
运维·服务器