1. 首页 > Podman教程 > 正文

Podman教程FG026-Podman容器镜像构建

本文档风哥主要介绍Podman容器镜像构建,包括镜像的概念、结构、类型以及镜像构建策略、工具和优化等内容。风哥教程参考Podman官方文档Image Building部分,适合容器管理员和开发人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

Part01-基础概念与理论知识

1.1 镜像概念

容器镜像是一个轻量级、可执行的独立软件包,包含运行应用所需的所有内容,包括代码、运行时、库、环境变量和配置文件。Podman容器镜像是符合OCI(Open Container Initiative)标准的镜像,可以在Podman和其他兼容OCI的容器运行时中使用。更多视频教程www.fgedu.net.cn

镜像的特点:

  • 轻量级:镜像体积小,启动快
  • 可移植:可以在不同的环境中运行
  • 一致性:确保应用在不同环境中运行结果一致
  • 分层:采用分层存储,提高存储效率
  • 不可变:镜像一旦构建,就不可修改

1.2 镜像结构

Podman容器镜像的结构主要包括:

  • 基础层:通常是操作系统的基础镜像,如Alpine、Ubuntu等
  • 应用层:包含应用代码和依赖
  • 配置层:包含应用配置文件
  • 元数据:包含镜像的元数据,如作者、版本、标签等

1.3 镜像类型

Podman容器镜像的类型主要包括:

  • 基础镜像:如Alpine、Ubuntu等操作系统镜像
  • 应用镜像:包含特定应用的镜像,如Nginx、MySQL等
  • 自定义镜像:根据特定需求构建的镜像
  • 多阶段构建镜像:通过多阶段构建减少镜像体积
风哥提示:容器镜像是容器运行的基础,通过合理构建和管理镜像,可以提高容器的性能和安全性。学习交流加群风哥微信: itpux-com

Part02-生产环境规划与建议

2.1 镜像构建策略

生产环境中Podman的镜像构建策略:

# 镜像构建策略

## 基础镜像选择
– 选择轻量级基础镜像:如Alpine、Distroless等
– 选择官方镜像:确保镜像的安全性和可靠性
– 定期更新基础镜像:修复安全漏洞

## 构建流程
– 使用Dockerfile:标准化镜像构建过程
– 多阶段构建:减少镜像体积
– 缓存优化:合理使用缓存,提高构建速度
– 自动化构建:使用CI/CD工具自动化镜像构建

## 镜像版本管理
– 使用语义化版本:如v1.0.0
– 使用标签:如latest、stable等
– 定期清理:清理过期镜像,释放存储空间

## 镜像存储
– 使用私有镜像仓库:提高安全性和可控性
– 镜像备份:定期备份重要镜像
– 镜像同步:在多个仓库之间同步镜像

2.2 镜像构建工具

生产环境中Podman的镜像构建工具:

  • Podman Build:Podman自带的镜像构建工具
  • Buildah:专门用于构建OCI镜像的工具
  • Docker Build:Docker的镜像构建工具,与Podman兼容
  • CI/CD工具:如Jenkins、GitLab CI等,用于自动化构建

2.3 镜像优化

生产环境中Podman的镜像优化:

# 镜像优化

## 减少镜像体积
– 使用轻量级基础镜像:如Alpine
– 多阶段构建:只包含必要的文件
– 清理临时文件:在构建过程中清理临时文件
– 最小化安装:只安装必要的依赖

## 提高构建速度
– 使用缓存:合理使用Dockerfile缓存
– 并行构建:使用CI/CD工具并行构建
– 本地构建:在本地构建镜像,减少网络传输

## 提高安全性
– 扫描镜像:使用工具扫描镜像中的安全漏洞
– 签名镜像:对镜像进行签名,确保镜像完整性
– 最小权限:容器只拥有必要的权限
– 定期更新:更新镜像中的依赖,修复安全漏洞

## 提高可维护性
– 分层构建:合理分层,便于维护
– 注释:在Dockerfile中添加注释,提高可读性
– 标准化:使用标准化的构建流程和配置
– 文档:编写镜像构建文档,便于他人理解

生产环境建议:合理选择镜像构建策略和工具,优化镜像体积和构建速度,提高镜像的安全性和可维护性。学习交流加群风哥QQ113257174

Part03-生产环境项目实施方案

3.1 Dockerfile基础构建

3.1.1 编写Dockerfile

# 编写Dockerfile

# 创建Dockerfile
$ cat > /Podman/fgdata/dockerfiles/Dockerfile << EOF FROM docker.io/library/ubuntu:22.04 LABEL maintainer="fengge@fgedu.net.cn" LABEL version="1.0" LABEL description="Ubuntu-based image with Nginx" RUN apt-get update && apt-get install -y \ nginx \ && rm -rf /var/lib/apt/lists/* COPY nginx.conf /etc/nginx/nginx.conf COPY index.html /usr/share/nginx/html/index.html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] EOF # 创建nginx.conf $ cat > /Podman/fgdata/dockerfiles/nginx.conf << EOF user nginx; worker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } } } EOF # 创建index.html $ cat > /Podman/fgdata/dockerfiles/index.html << EOF

Hello from Podman!

This is a custom Nginx image built with Podman.

EOF

# 构建镜像
$ podman build -t fgedu/nginx:1.0 -f /Podman/fgdata/dockerfiles/Dockerfile /Podman/fgdata/dockerfiles

# 输出日志
STEP 1: FROM docker.io/library/ubuntu:22.04
STEP 2: LABEL maintainer=”fengge@fgedu.net.cn”
STEP 3: LABEL version=”1.0″
STEP 4: LABEL description=”Ubuntu-based image with Nginx”
STEP 5: RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/*
–> Using cache b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7
–> b7f8a9b7a9b7
STEP 6: COPY nginx.conf /etc/nginx/nginx.conf
–> Using cache c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3
–> c8d9e0f1e2f3
STEP 7: COPY index.html /usr/share/nginx/html/index.html
–> Using cache d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8
–> d9e0f1e2f3c8
STEP 8: EXPOSE 80
STEP 9: CMD [“nginx”, “-g”, “daemon off;”]
STEP 10: COMMIT fgedu/nginx:1.0
–> f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7a9
Successfully tagged localhost/fgedu/nginx:1.0

# 查看镜像
$ podman images

# 输出日志
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/fgedu/nginx 1.0 f8a9b7a9b7a9 2 minutes ago 180 MB

3.2 多阶段构建

3.2.1 多阶段构建示例

# 多阶段构建示例

# 创建Dockerfile
$ cat > /Podman/fgdata/dockerfiles/Dockerfile.multi << EOF # 构建阶段 FROM docker.io/library/node:18-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm install COPY . . RUN npm run build # 运行阶段 FROM docker.io/library/nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] EOF # 创建package.json $ cat > /Podman/fgdata/dockerfiles/package.json << EOF { "name": "react-app", "version": "1.0.0", "description": "React application", "scripts": { "start": "react-scripts start", "build": "react-scripts build" }, "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1" } } EOF # 创建nginx.conf $ cat > /Podman/fgdata/dockerfiles/nginx.conf << EOF server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; try_files uri uri/ /index.html; } } EOF # 构建镜像 $ podman build -t fgedu/react-app:1.0 -f /Podman/fgdata/dockerfiles/Dockerfile.multi /Podman/fgdata/dockerfiles # 输出日志 STEP 1: FROM docker.io/library/node:18-alpine AS builder STEP 2: WORKDIR /app STEP 3: COPY package.json package-lock.json ./ STEP 4: RUN npm install --> Using cache b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7
–> b7f8a9b7a9b7
STEP 5: COPY . .
STEP 6: RUN npm run build
–> Using cache c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3
–> c8d9e0f1e2f3
STEP 7: FROM docker.io/library/nginx:alpine
STEP 8: COPY –from=builder /app/build /usr/share/nginx/html
–> Using cache d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8
–> d9e0f1e2f3c8
STEP 9: COPY nginx.conf /etc/nginx/conf.d/default.conf
–> Using cache e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9
–> e0f1e2f3c8d9
STEP 10: EXPOSE 80
STEP 11: CMD [“nginx”, “-g”, “daemon off;”]
STEP 12: COMMIT fgedu/react-app:1.0
–> f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7a9
Successfully tagged localhost/fgedu/react-app:1.0

# 查看镜像
$ podman images

# 输出日志
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/fgedu/react-app 1.0 f8a9b7a9b7a9 2 minutes ago 50 MB

3.3 镜像仓库

3.3.1 私有镜像仓库部署

# 私有镜像仓库部署

# 运行私有镜像仓库容器
$ podman run -d –name fgedu-registry \
-v /Podman/fgdata/registry:/var/lib/registry:z \
-p 5000:5000 \
docker.io/library/registry:2

# 查看容器状态
$ podman ps

# 输出日志
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7890123456ab docker.io/library/registry /entrypoint.sh /e 2 minutes ago Up 2 minutes ago 0.0.0.0:5000->5000/tcp fgedu-registry

# 标记镜像
$ podman tag fgedu/nginx:1.0 localhost:5000/fgedu/nginx:1.0

# 推送镜像到私有仓库
$ podman push localhost:5000/fgedu/nginx:1.0

# 输出日志
Getting image source signatures
Copying blob sha256:b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7
Copying blob sha256:c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3
Copying blob sha256:d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8d9e0f1e2f3c8
Copying config sha256:f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7f8a9b7a9b7a9
Writing manifest to image destination
Storing signatures

# 拉取镜像
$ podman pull localhost:5000/fgedu/nginx:1.0

# 查看镜像
$ podman images

# 输出日志
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost:5000/fgedu/nginx 1.0 f8a9b7a9b7a9 10 minutes ago 180 MB

风哥提示:镜像仓库是存储和管理镜像的重要设施,通过部署私有镜像仓库,可以提高镜像的安全性和可控性。更多学习教程公众号风哥教程itpux_com

Part04-生产案例与实战讲解

4.1 Web应用镜像构建

4.1.1 构建Nginx镜像

# 构建Nginx镜像

# 创建Dockerfile
$ cat > /Podman/fgdata/dockerfiles/Dockerfile.nginx << EOF FROM docker.io/library/nginx:alpine LABEL maintainer="fengge@fgedu.net.cn" LABEL version="1.0" LABEL description="Nginx image for web application" COPY nginx.conf /etc/nginx/nginx.conf COPY html/ /usr/share/nginx/html/ EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] EOF # 创建nginx.conf $ cat > /Podman/fgdata/dockerfiles/nginx.conf << EOF user nginx; worker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } } } EOF # 创建html目录 $ mkdir -p /Podman/fgdata/dockerfiles/html # 创建index.html $ cat > /Podman/fgdata/dockerfiles/html/index.html << EOF

Hello from Podman!

This is a custom Nginx image built with Podman.

EOF

# 构建镜像
$ podman build -t fgedu/nginx:1.0 -f /Podman/fgdata/dockerfiles/Dockerfile.nginx /Podman/fgdata/dockerfiles

# 运行容器
$ podman run -d –name fgedu-nginx \
-p 80:80 \
fgedu/nginx:1.0

# 测试服务
$ curl http://localhost

# 输出日志

Hello from Podman!

This is a custom Nginx image built with Podman.

4.2 数据库镜像构建

4.2.1 构建MySQL镜像

# 构建MySQL镜像

# 创建Dockerfile
$ cat > /Podman/fgdata/dockerfiles/Dockerfile.mysql << EOF FROM docker.io/library/mysql:8.0 LABEL maintainer="fengge@fgedu.net.cn" LABEL version="1.0" LABEL description="MySQL image with custom configuration" COPY my.cnf /etc/mysql/my.cnf COPY init.sql /docker-entrypoint-initdb.d/ ENV MYSQL_ROOT_PASSWORD=fgedu123 ENV MYSQL_DATABASE=fgedudb ENV MYSQL_USER=fgedu ENV MYSQL_PASSWORD=fgedu123 EXPOSE 3306 EOF # 创建my.cnf $ cat > /Podman/fgdata/dockerfiles/my.cnf << EOF [mysqld] bind-address = 0.0.0.0 max_connections = 100 innodb_buffer_pool_size = 256M EOF # 创建init.sql $ cat > /Podman/fgdata/dockerfiles/init.sql << EOF CREATE TABLE fgedu_test ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), value VARCHAR(255) ); INSERT INTO fgedu_test (name, value) VALUES ('test1', 'value1'), ('test2', 'value2'), ('test3', 'value3'); EOF # 构建镜像 $ podman build -t fgedu/mysql:1.0 -f /Podman/fgdata/dockerfiles/Dockerfile.mysql /Podman/fgdata/dockerfiles # 运行容器 $ podman run -d --name fgedu-mysql \ -v /Podman/fgdata/mysql/data:/var/lib/mysql:z \ -p 3306:3306 \ fgedu/mysql:1.0 # 测试服务 $ podman exec -it fgedu-mysql mysql -u fgedu -p fgedudb # 输出日志 Enter password: mysql> SELECT * FROM fgedu_test;

# 输出日志
+—-+——-+——–+
| id | name | value |
+—-+——-+——–+
| 1 | test1 | value1 |
| 2 | test2 | value2 |
| 3 | test3 | value3 |
+—-+——-+——–+

mysql> exit

4.3 微服务镜像构建

4.3.1 构建Node.js微服务镜像

# 构建Node.js微服务镜像

# 创建Dockerfile
$ cat > /Podman/fgdata/dockerfiles/Dockerfile.node << EOF FROM docker.io/library/node:18-alpine LABEL maintainer="fengge@fgedu.net.cn" LABEL version="1.0" LABEL description="Node.js microservice image" WORKDIR /app COPY package.json package-lock.json ./ RUN npm install --production COPY . . EXPOSE 3000 CMD ["node", "server.js"] EOF # 创建package.json $ cat > /Podman/fgdata/dockerfiles/package.json << EOF { "name": "node-microservice", "version": "1.0.0", "description": "Node.js microservice", "main": "server.js", "scripts": { "start": "node server.js" }, "dependencies": { "express": "^4.18.2" } } EOF # 创建server.js $ cat > /Podman/fgdata/dockerfiles/server.js << EOF const express = require('express'); const app = express(); const port = 3000; app.get('/', (req, res) => {
res.json({ message: ‘Hello from Node.js microservice!’ });
});

app.get(‘/health’, (req, res) => {
res.json({ status: ‘healthy’ });
});

app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
EOF

# 构建镜像
$ podman build -t fgedu/node-microservice:1.0 -f /Podman/fgdata/dockerfiles/Dockerfile.node /Podman/fgdata/dockerfiles

# 运行容器
$ podman run -d –name fgedu-node \
-p 3000:3000 \
fgedu/node-microservice:1.0

# 测试服务
$ curl http://localhost:3000

# 输出日志
{“message”: “Hello from Node.js microservice!”}

# 测试健康检查
$ curl http://localhost:3000/health

# 输出日志
{“status”: “healthy”}

生产环境建议:在生产环境中,应建立完善的镜像构建和管理流程,确保镜像的质量和安全性,满足业务需求。from Podman视频:www.itpux.com

Part05-风哥经验总结与分享

5.1 镜像构建最佳实践

Podman容器镜像构建的最佳实践:

  • 使用轻量级基础镜像:如Alpine、Distroless等,减少镜像体积
  • 多阶段构建:使用多阶段构建减少镜像体积,只包含必要的文件
  • 合理使用缓存:在Dockerfile中合理安排命令顺序,提高构建速度
  • 最小化安装:只安装必要的依赖,减少镜像体积和安全漏洞
  • 清理临时文件:在构建过程中清理临时文件,减少镜像体积
  • 标准化构建:使用标准化的Dockerfile模板,提高可维护性
  • 自动化构建:使用CI/CD工具自动化镜像构建,提高效率
  • 镜像版本管理:使用语义化版本和标签,便于管理和追溯

5.2 镜像管理

Podman容器镜像管理:

# 镜像管理

## 查看镜像
$ podman images

## 查看镜像详情
$ podman inspect fgedu/nginx:1.0

## 标记镜像
$ podman tag fgedu/nginx:1.0 fgedu/nginx:latest

## 推送镜像
$ podman push fgedu/nginx:1.0

## 拉取镜像
$ podman pull fgedu/nginx:1.0

## 删除镜像
$ podman rmi fgedu/nginx:1.0

## 清理未使用的镜像
$ podman image prune

## 导出镜像
$ podman save -o fgedu-nginx.tar fgedu/nginx:1.0

## 导入镜像
$ podman load -i fgedu-nginx.tar

5.3 镜像安全

Podman容器镜像安全:

  • 使用官方镜像:只使用官方或可信来源的镜像
  • 定期更新:定期更新镜像,修复安全漏洞
  • 镜像扫描:使用工具扫描镜像中的安全漏洞
  • 签名镜像:对镜像进行签名,确保镜像完整性
  • 最小权限:容器只拥有必要的权限
  • 网络隔离:使用网络命名空间隔离容器网络
  • 存储隔离:使用存储命名空间隔离容器存储
  • 监控:监控容器的运行状态和网络流量
风哥提示:容器镜像构建是容器技术的核心环节,通过合理构建和管理镜像,可以提高容器的性能、安全性和可维护性。建议建立完善的镜像构建和管理流程,确保镜像的质量和安全性,满足业务需求。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息