本文档风哥主要介绍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等
- 自定义镜像:根据特定需求构建的镜像
- 多阶段构建镜像:通过多阶段构建减少镜像体积
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中添加注释,提高可读性
– 标准化:使用标准化的构建流程和配置
– 文档:编写镜像构建文档,便于他人理解
Part03-生产环境项目实施方案
3.1 Dockerfile基础构建
3.1.1 编写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
Part04-生产案例与实战讲解
4.1 Web应用镜像构建
4.1.1 构建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镜像
# 创建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微服务镜像
# 创建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”}
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
