Perl 完全指南 / 第 22 章:Docker 中的 Perl
第 22 章:Docker 中的 Perl
“Build once, run anywhere”
Docker 是现代应用部署的标准方式。本章介绍如何将 Perl 应用容器化。
22.1 Perl Docker 镜像
官方镜像
| 镜像 | 大小 | 说明 |
|---|---|---|
perl:5.40 | ~350MB | 完整镜像(Debian) |
perl:5.40-slim | ~80MB | 精简镜像(推荐) |
perl:5.40-threaded | ~380MB | 带线程支持 |
perl:5.40-bookworm | ~350MB | 指定 Debian 版本 |
# 拉取镜像
docker pull perl:5.40-slim
# 运行一次命令
docker run --rm perl:5.40-slim perl -e 'print "Hello from Docker!\n"'
# 交互式 shell
docker run -it --rm perl:5.40-slim bash
22.2 基本 Dockerfile
# Dockerfile
FROM perl:5.40-slim
# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
make \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# 安装 cpanm
RUN curl -L https://cpanmin.us | perl - App::cpanminus
# 设置工作目录
WORKDIR /app
# 先复制依赖文件(利用 Docker 缓存)
COPY cpanfile cpanfile
RUN cpanm --notest --installdeps .
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["perl", "script/myapp", "daemon", "-l", "http://*:3000"]
22.3 多阶段构建
# 多阶段构建 — 减小最终镜像
# 阶段 1:构建
FROM perl:5.40 AS builder
WORKDIR /build
COPY cpanfile cpanfile
RUN cpanm --notest --installdeps .
COPY . .
RUN perl Makefile.PL && make && make test
# 阶段 2:运行
FROM perl:5.40-slim
# 复制 Perl 库
COPY --from=builder /usr/local/lib/perl5 /usr/local/lib/perl5
COPY --from=builder /usr/local/bin /usr/local/bin
WORKDIR /app
COPY . .
EXPOSE 3000
CMD ["perl", "script/myapp", "daemon", "-l", "http://*:3000"]
22.4 使用 Carton 管理依赖
FROM perl:5.40-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc make libssl-dev \
&& rm -rf /var/lib/apt/lists/*
RUN cpanm --notest Carton
WORKDIR /app
COPY cpanfile cpanfile.snapshot ./
RUN carton install --deployment --without develop
COPY . .
EXPOSE 3000
CMD ["carton", "exec", "perl", "script/myapp", "daemon", "-l", "http://*:3000"]
22.5 docker-compose 配置
# docker-compose.yml
version: "3.8"
services:
web:
build: .
ports:
- "3000:3000"
environment:
- MOJO_MODE=production
- DATABASE_URL=dbi:SQLite:dbname=/data/app.db
volumes:
- app_data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
# 如果使用 PostgreSQL
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: secret
volumes:
- pg_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
app_data:
pg_data:
22.6 生产环境优化
.dockerignore
.git
.gitignore
t/
*.tar.gz
*.bak
public/
nytprof*
local/
安全最佳实践
# 使用非 root 用户
FROM perl:5.40-slim
RUN groupadd -r perl && useradd -r -g perl -d /app perl
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --chown=perl:perl . .
USER perl
EXPOSE 3000
CMD ["perl", "script/myapp", "daemon", "-l", "http://*:3000"]
资源限制
# 限制 CPU 和内存
docker run -d \
--name myapp \
--memory=512m \
--cpus=1.0 \
--restart=unless-stopped \
-p 3000:3000 \
myapp:latest
22.7 业务场景:完整的 Mojolicious 应用部署
项目结构
myapp/
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
├── cpanfile
├── cpanfile.snapshot
├── script/
│ └── myapp
├── lib/
│ └── MyApp.pm
│ └── MyApp/
├── templates/
├── public/
└── t/
Nginx 反向代理配置
# nginx.conf
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://web:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static/ {
alias /app/public/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
完整 docker-compose
version: "3.8"
services:
web:
build:
context: .
dockerfile: Dockerfile
environment:
MOJO_MODE: production
MOJO_SECRET: your-secret-key-here
expose:
- "3000"
restart: unless-stopped
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./public:/app/public:ro
depends_on:
- web
restart: unless-stopped
本章小结
| 要点 | 内容 |
|---|---|
perl:5.40-slim | 推荐的基础镜像 |
| 多阶段构建 | 减小最终镜像体积 |
| Carton | Docker 中管理依赖的最佳方式 |
| .dockerignore | 排除不必要的文件 |
| 非 root 用户 | 生产环境安全最佳实践 |
| docker-compose | 多服务编排 |
练习
- 为你的 Perl 应用编写 Dockerfile
- 使用多阶段构建优化镜像大小
- 使用 docker-compose 编排 Perl 应用 + Nginx
- 配置健康检查
- 尝试使用
perl:5.40-slimvsperl:5.40对比镜像大小