【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 中完成。
相关推荐
胡斌附体1 小时前
docker desktop 限制wsl使用内存空间
docker·docker desktop·wsl·卡死·限制内存占用·限制内存
拾心211 小时前
【云运维】Kubernetes安装(基于 Docker + Calico)
运维·docker·kubernetes
q***51891 小时前
离线安装 Nginx
运维·数据库·nginx
我也要当昏君2 小时前
4.1.8 【2022 统考真题】
运维·服务器·网络
Caster_Z2 小时前
Windows环境安装Docker
运维·docker·容器
磊〜2 小时前
Linux 服务器安装 dstat 监控插件
linux·运维·服务器
不老刘2 小时前
使用 Docker Compose 一键更新:深入理解 docker-compose pull 的适用场景
docker·容器·eureka·cline
百***07182 小时前
IDEA+Docker一键部署项目SpringBoot项目
spring boot·docker·intellij-idea
二进制coder2 小时前
服务器BMC开发视角:解析CPU管理的两大核心接口PECI与APML
运维·服务器·网络