在 Podman 中,可通过 podman build 命令根据 Containerfile 或 Dockerfile 构建容器镜像,功能与 docker build 类似,支持基于指令分步构建镜像,且完全兼容 Docker 的构建语法。
podman build 命令将读取指定路径下的 Containerfile(默认文件名),按照文件中的指令(如 FROM、RUN、COPY 等)逐步构建镜像层,最终生成可运行的容器镜像。
下面是 podman build 命令的基本语法:
podman build [选项] 构建上下文路径
构建上下文(Context):构建时指定的路径(目录),该目录下的所有文件会被发送到 Podman 守护进程,供 COPY、ADD 等指令使用。
常用选项说明:
-t, --tag 为构建的镜像指定标签(格式:名称:标签),可多次使用指定多个标签。示例:-t myapp:v1 -t myapp:latest
-f, --file 指定自定义构建文件(非默认 Containerfile 时使用)。示例:-f ./build/Dockerfile.prod
--build-arg 传递构建时变量(对应 Dockerfile 中的 ARG 指令)。示例:--build-arg VERSION=1.0
--no-cache 不使用缓存,强制重新执行所有构建步骤(避免缓存导致的旧内容残留)。
--rm 构建完成后自动删除中间容器(默认启用,--rm=false 可保留中间容器用于调试)。
--platform 指定构建镜像的目标平台(如 linux/amd64、linux/arm64),需配合多架构构建支持。
-q, --quiet 静默模式,仅输出最终镜像 ID,不显示构建过程日志。
--pull 字符串[="always"] 拉取镜像策略("always"|"missing"|"never"|"newer")(默认 "missing")
更多选项参考 podman build 命令参考手册。
为了后续顺利进行,这里特意提供了一个简单的 nginx 镜像 Containerfile 文件,内容如下:
# 基础镜像:使用官方 Nginx 稳定版(Alpine 版本,体积更小) FROM nginx:stable-alpine # 维护者信息(可选) LABEL maintainer="hxstrive@outlook.com" LABEL description="Custom Nginx image with custom config and static files" # 更换 Alpine 镜像源为国内源(加速依赖安装,可选) #RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories # 安装必要工具(如 curl 用于健康检查,可选) RUN apk update && \ apk add --no-cache curl && \ rm -rf /var/cache/apk/* # 清理缓存,减小镜像体积 # 复制自定义 Nginx 配置文件(覆盖默认配置) # 假设当前目录有 nginx.conf(主配置)和 conf.d/ 目录(虚拟主机配置) COPY nginx.conf /etc/nginx/nginx.conf COPY conf.d/ /etc/nginx/conf.d/ # 复制自定义静态网页到 Nginx 默认站点目录 # 假设当前目录有 html/ 目录,包含 index.html 等文件 COPY html/ /usr/share/nginx/html/ # 调整文件权限(避免容器内权限问题,尤其是 rootless 模式下) RUN chown -R nginx:nginx /usr/share/nginx/html /var/log/nginx && \ chmod -R 755 /usr/share/nginx/html # 配置 Nginx 日志输出到标准输出(便于容器日志收集,如 podman logs) RUN ln -sf /dev/stdout /var/log/nginx/access.log && \ ln -sf /dev/stderr /var/log/nginx/error.log # 暴露 Nginx 默认端口(80 或 443,根据配置文件调整) EXPOSE 80 # EXPOSE 443 # 若启用 HTTPS,取消注释 # 健康检查:定期检查 Nginx 服务是否正常(可选) # HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ # CMD curl -f http://localhost/ || exit 1 # 启动命令(使用官方默认,无需修改,Nginx 以非 daemon 模式运行) CMD ["nginx", "-g", "daemon off;"]
完整信息参考:Containerfile 实战:自己的 Nginx 镜像
在当前目录下寻找 Containerfile,构建镜像并标记为 myapp:v1:
podman build -t myapp:v1 .
注意:“.”表示构建上下文为当前目录(所有文件会被纳入构建范围)。
D:\Podman\nginx-custom> podman build -t myapp:v1 . STEP 1/11: FROM nginx:stable-alpine Resolving "nginx" using unqualified-search registries (/home/user/.config/containers/registries.conf) Trying to pull docker.io/library/nginx:stable-alpine... Getting image source signatures Copying blob sha256:c4fca37af7b3b885e76d1a14e76d630444c2868b27ff67848e077142d9771faa Copying blob sha256:8e049f0fd1511eaabb03da73d0582501fd3a012ddb00620ff653b1a13b646310 Copying blob sha256:71a39d0d04b2893246ec57f9cf1b074a63fd0f094098a8b1741d0e625f4009c1 Copying blob sha256:e6918dcfd20da0647335265f4647268123ce772646f9dea11cae650f26be0276 Copying blob sha256:f637881d1138581d892d9eb942c56e0ccc7758fe3bdc0f1e6cd66059fdfd8185 Copying blob sha256:b8554c5f1ad0265d1dc3a5f23b3b52e93fa1cdeda0c6b54618d3f9168e6ed01b Copying blob sha256:bc1d7488b05ed88bc5975378fd4ef0f1ea4b6114d13fa5cbeec6a572588e0c00 Copying blob sha256:3e300a7cb18c79c3ddadf170ae2c540c8feafdf7fcdc6cd5d5a3cd229fb0cada Copying config sha256:c318e336065b17ff460aeac6d14bce5d0b13e35f25d5cb1843b635359fc00c9a Writing manifest to image destination STEP 2/11: LABEL maintainer="hxstrive@outlook.com" --> 9bdaee115371 STEP 3/11: LABEL description="Custom Nginx image with custom config and static files" --> 25e42c577947 STEP 4/11: RUN apk update && apk add --no-cache curl && rm -rf /var/cache/apk/* # 清理缓存,减小镜像体积 fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz v3.21.5-75-g1ace668154e [https://dl-cdn.alpinelinux.org/alpine/v3.21/main] v3.21.5-74-g3749f9c5659 [https://dl-cdn.alpinelinux.org/alpine/v3.21/community] OK: 25403 distinct packages available fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz OK: 45 MiB in 68 packages --> 2cd6ec07db11 STEP 5/11: COPY nginx.conf /etc/nginx/nginx.conf --> 66f18af4c329 STEP 6/11: COPY conf.d/ /etc/nginx/conf.d/ --> 312172934889 STEP 7/11: COPY html/ /usr/share/nginx/html/ --> eadeb4df71d7 STEP 8/11: RUN chown -R nginx:nginx /usr/share/nginx/html /var/log/nginx && chmod -R 755 /usr/share/nginx/html --> 3a10a23e62ab STEP 9/11: RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log --> dcbb61f0482b STEP 10/11: EXPOSE 80 --> 01bc606a1c22 STEP 11/11: CMD ["nginx", "-g", "daemon off;"] COMMIT myapp:v1 --> fd16466b1336 Successfully tagged localhost/myapp:v1 fd16466b13362d56c8af4c985767ef3707171614f76780745c5c885a120b5e0e D:\Podman\nginx-custom> podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/myapp v1 fd16466b1336 7 seconds ago 49.9 MB
指定路径为 ./nginx-custom下的 Containerfile 作为构建文件,./nginx-custom 为构建上下文,构建镜像:
podman build -f ./nginx-custom/Containerfile -t myapp:1.0 ./nginx-custom
注意:-f 指定构建文件路径,./nginx-custom 为构建上下文(仅 ./nginx-custom 目录下的文件可被 COPY 等指令访问)。
D:\Podman> podman build -f ./nginx-custom/Containerfile -t myapp:1.0 ./nginx-custom STEP 1/11: FROM nginx:stable-alpine Resolving "nginx" using unqualified-search registries (/home/user/.config/containers/registries.conf) Trying to pull docker.io/library/nginx:stable-alpine... Getting image source signatures Copying blob sha256:c4fca37af7b3b885e76d1a14e76d630444c2868b27ff67848e077142d9771faa Copying blob sha256:b8554c5f1ad0265d1dc3a5f23b3b52e93fa1cdeda0c6b54618d3f9168e6ed01b Copying blob sha256:f637881d1138581d892d9eb942c56e0ccc7758fe3bdc0f1e6cd66059fdfd8185 Copying blob sha256:71a39d0d04b2893246ec57f9cf1b074a63fd0f094098a8b1741d0e625f4009c1 Copying blob sha256:8e049f0fd1511eaabb03da73d0582501fd3a012ddb00620ff653b1a13b646310 Copying blob sha256:e6918dcfd20da0647335265f4647268123ce772646f9dea11cae650f26be0276 Copying blob sha256:bc1d7488b05ed88bc5975378fd4ef0f1ea4b6114d13fa5cbeec6a572588e0c00 Copying blob sha256:3e300a7cb18c79c3ddadf170ae2c540c8feafdf7fcdc6cd5d5a3cd229fb0cada Copying config sha256:c318e336065b17ff460aeac6d14bce5d0b13e35f25d5cb1843b635359fc00c9a Writing manifest to image destination STEP 2/11: LABEL maintainer="hxstrive@outlook.com" --> 0049ed606a3e STEP 3/11: LABEL description="Custom Nginx image with custom config and static files" --> 0c02adbbff11 STEP 4/11: RUN apk update && apk add --no-cache curl && rm -rf /var/cache/apk/* # 清理缓存,减小镜像体积 fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz v3.21.5-75-g1ace668154e [https://dl-cdn.alpinelinux.org/alpine/v3.21/main] v3.21.5-74-g3749f9c5659 [https://dl-cdn.alpinelinux.org/alpine/v3.21/community] OK: 25403 distinct packages available fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz OK: 45 MiB in 68 packages --> 9cf27c3c03a0 STEP 5/11: COPY nginx.conf /etc/nginx/nginx.conf --> 148fc1c6a7d4 STEP 6/11: COPY conf.d/ /etc/nginx/conf.d/ --> 23eff84b5691 STEP 7/11: COPY html/ /usr/share/nginx/html/ --> 3bbd2dd53cd6 STEP 8/11: RUN chown -R nginx:nginx /usr/share/nginx/html /var/log/nginx && chmod -R 755 /usr/share/nginx/html --> f958cc426b09 STEP 9/11: RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log --> ce9018e4f573 STEP 10/11: EXPOSE 80 --> 87d20abd7d01 STEP 11/11: CMD ["nginx", "-g", "daemon off;"] COMMIT myapp:1.0 --> e53e79369d55 Successfully tagged localhost/myapp:1.0 e53e79369d55d7cbe0a7cb1db20fb40350957f0d069ae1565834b128bf8e35d5 D:\Podman> podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/myapp 1.0 e53e79369d55 6 seconds ago 49.9 MB docker.io/library/nginx stable-alpine c318e336065b 6 months ago 49.7 MB
假设 Containerfile 中定义了 ARG APP_PORT,构建时可以通过 --build-arg 选项传入参数并指定端口:
podman build --build-arg APP_PORT=8080 -t myapp:with-port .
为了演示传递构建参数,这里特意提供一个 Containerfile 示例,演示如何在构建镜像时传递和使用构建参数(build arguments):
# 基于官方Alpine镜像
FROM alpine:latest
# 定义构建参数(ARG),可以设置默认值
ARG APP_VERSION=1.0.0
ARG APP_ENV=production
ARG AUTHOR_NAME=Unknown
# 将构建参数设置为环境变量
ENV APP_VERSION=${APP_VERSION}
ENV APP_ENV=${APP_ENV}
ENV AUTHOR_NAME=${AUTHOR_NAME}
# 使用构建参数执行命令
RUN echo "Building application version: ${APP_VERSION}" && \
echo "Environment: ${APP_ENV}" && \
echo "Author: ${AUTHOR_NAME}" > /app_info.txt
# 显示构建信息
RUN cat /app_info.txt
# 先输出信息,然后启动交互式shell
CMD ["sh", "-c", "echo \"App Version: $APP_VERSION, Env: $APP_ENV, Author: $AUTHOR_NAME\"; exec /bin/sh"]使用 podman build 构建镜像且传递 APP_VERSION、APP_ENV 等参数,如下:
D:\Podman\args> podman build --build-arg APP_VERSION=2.1.5 --build-arg APP_ENV=development --build-arg AUTHOR_NAME="John Doe" -t arg-demo:custom .
STEP 1/10: FROM alpine:latest
STEP 2/10: ARG APP_VERSION=1.0.0
--> Using cache 7d31d5763f3a0c2e672f344fc8630d34859eda22c7849edb4b9e346640f4ebd8
--> 7d31d5763f3a
STEP 3/10: ARG APP_ENV=production
--> Using cache 357f196753f1a51188319421c64decc720dea96be89502811334ec818eae6594
--> 357f196753f1
STEP 4/10: ARG AUTHOR_NAME=Unknown
--> Using cache 63cf892404920f1204ebfbccd4f4866a01b9c95debaf920055d94e3b432bfe07
--> 63cf89240492
STEP 5/10: ENV APP_VERSION=${APP_VERSION}
--> Using cache e7216956349555d7d92967c9c749a4c0c6b47eaed275e00305549798c97d463a
--> e72169563495
STEP 6/10: ENV APP_ENV=${APP_ENV}
--> Using cache 58ee43658c71921037d1dfd7c36a1a8b13f51d8ffd1f49c2e6cbea7e0597eac9
--> 58ee43658c71
STEP 7/10: ENV AUTHOR_NAME=${AUTHOR_NAME}
--> a3159f99e73c
STEP 8/10: RUN echo "Building application version: ${APP_VERSION}" && echo "Environment: ${APP_ENV}" && echo "Author: ${AUTHOR_NAME}" > /app_info.txt
Building application version: 2.1.5
Environment: development
--> 80599f2ed74e
STEP 9/10: RUN cat /app_info.txt
Author: John Doe
--> 0ac675f753ca
STEP 10/10: CMD ["sh", "-c", "echo \"App Version: $APP_VERSION, Env: $APP_ENV, Author: $AUTHOR_NAME\"; exec /bin/sh"]
COMMIT arg-demo:custom
--> c3ee6177e88b
Successfully tagged localhost/arg-demo:custom
c3ee6177e88be1b3079a08bcfcda6135d666c154fafa25edb1d6a7269ca94ed3运行容器,验证参数是否传递到镜像中,如下:
D:\Podman\args> podman run --rm arg-demo:custom App Version: 2.1.5, Env: development, Author: John Doe
从输出可以看到,App 的版本信息、环境、作者信息
避免因缓存导致的旧依赖残留,强制重新执行所有步骤:
podman build --no-cache -t myapp:fresh .
同时为镜像添加 v2 和 latest 标签:
podman build -t myapp:v2 -t myapp:latest .
例如:
D:\Podman\nginx-custom> podman build -t myapp:v2 -t myapp:latest . STEP 1/11: FROM nginx:stable-alpine Resolving "nginx" using unqualified-search registries (/home/user/.config/containers/registries.conf) Trying to pull docker.io/library/nginx:stable-alpine... Getting image source signatures Copying blob sha256:c4fca37af7b3b885e76d1a14e76d630444c2868b27ff67848e077142d9771faa Copying blob sha256:71a39d0d04b2893246ec57f9cf1b074a63fd0f094098a8b1741d0e625f4009c1 Copying blob sha256:b8554c5f1ad0265d1dc3a5f23b3b52e93fa1cdeda0c6b54618d3f9168e6ed01b Copying blob sha256:f637881d1138581d892d9eb942c56e0ccc7758fe3bdc0f1e6cd66059fdfd8185 Copying blob sha256:e6918dcfd20da0647335265f4647268123ce772646f9dea11cae650f26be0276 Copying blob sha256:8e049f0fd1511eaabb03da73d0582501fd3a012ddb00620ff653b1a13b646310 Copying blob sha256:bc1d7488b05ed88bc5975378fd4ef0f1ea4b6114d13fa5cbeec6a572588e0c00 Copying blob sha256:3e300a7cb18c79c3ddadf170ae2c540c8feafdf7fcdc6cd5d5a3cd229fb0cada Copying config sha256:c318e336065b17ff460aeac6d14bce5d0b13e35f25d5cb1843b635359fc00c9a Writing manifest to image destination STEP 2/11: LABEL maintainer="hxstrive@outlook.com" --> b10d73cf4e86 STEP 3/11: LABEL description="Custom Nginx image with custom config and static files" --> bbc21c026aca STEP 4/11: RUN apk update && apk add --no-cache curl && rm -rf /var/cache/apk/* # 清理缓存,减小镜像体积 fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz v3.21.5-75-g1ace668154e [https://dl-cdn.alpinelinux.org/alpine/v3.21/main] v3.21.5-74-g3749f9c5659 [https://dl-cdn.alpinelinux.org/alpine/v3.21/community] OK: 25403 distinct packages available fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.21/community/x86_64/APKINDEX.tar.gz OK: 45 MiB in 68 packages --> 352316f64f6b STEP 5/11: COPY nginx.conf /etc/nginx/nginx.conf --> 371f65551712 STEP 6/11: COPY conf.d/ /etc/nginx/conf.d/ --> 3e03ca7c5c83 STEP 7/11: COPY html/ /usr/share/nginx/html/ --> 391659dfee22 STEP 8/11: RUN chown -R nginx:nginx /usr/share/nginx/html /var/log/nginx && chmod -R 755 /usr/share/nginx/html --> 2cd9f973b0de STEP 9/11: RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log --> 8dfb79679b22 STEP 10/11: EXPOSE 80 --> 9949b484705a STEP 11/11: CMD ["nginx", "-g", "daemon off;"] COMMIT myapp:v2 --> cca6bb653dae Successfully tagged localhost/myapp:latest Successfully tagged localhost/myapp:v2 cca6bb653dae7b35893d62486e305b5324c3326d258266292e7715a471dcad66 D:\Podman\nginx-custom> podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/myapp latest cca6bb653dae 6 seconds ago 49.9 MB localhost/myapp v2 cca6bb653dae 6 seconds ago 49.9 MB docker.io/library/nginx stable-alpine c318e336065b 6 months ago 49.7 MB
注意:podman build 完全兼容 Docker 的构建逻辑,因此基于 Dockerfile 的现有构建流程可无缝迁移到 Podman 中使用。
更多内容请参考官方网文档。