DeepSeek生成(2025年10月28日22:41:17)
目录
Docker 打包 Nginx 完整教学
Docker 基础概念
什么是 Docker?
Docker 是一个开源的应用容器引擎,可以让开发者打包他们的应用以及依赖包到一个可移植的容器中。
核心概念:
- 镜像(Image):类似于虚拟机的快照,包含运行应用所需的所有内容
- 容器(Container):镜像的运行实例
- Dockerfile:用于构建镜像的脚本文件
- 仓库(Registry):存放镜像的地方,如 Docker Hub
Nginx 简介
Nginx 是一个高性能的 HTTP 和反向代理服务器,常用于:
- 静态网站服务
- 负载均衡
- API 网关
- 反向代理
Dockerfile 详解
Dockerfile 基本结构
Dockerfile 是由一系列指令和参数构成的文本文件,每条指令都会在镜像上创建一个新的层。
常用指令:
FROM:指定基础镜像RUN:执行命令COPY:复制文件ADD:复制文件(功能更强大)EXPOSE:声明端口CMD:容器启动命令ENTRYPOINT:容器入口点ENV:设置环境变量WORKDIR:设置工作目录
实战:创建 Nginx Docker 镜像
基础版本 Dockerfile
让我们从最简单的 Nginx Dockerfile 开始:
# 使用官方 Nginx 镜像作为基础
FROM nginx:latest
# 维护者信息(可选)
LABEL maintainer="your-email@example.com"
# 将本地的静态文件复制到容器中的 Nginx 默认目录
COPY ./html /usr/share/nginx/html
# 暴露 80 端口
EXPOSE 80
# 启动 Nginx(基础镜像已包含,此处可省略)
CMD ["nginx", "-g", "daemon off;"]
详细解释:
-
FROM nginx:latest
- 使用官方 Nginx 镜像作为基础
latest标签表示使用最新版本
-
COPY ./html /usr/share/nginx/html
- 将本地
html目录复制到容器的 Nginx 默认网站目录 - 你需要提前准备好静态文件
- 将本地
-
EXPOSE 80
- 声明容器运行时监听的端口
- 这只是声明,实际映射需要在运行容器时指定
-
CMD ["nginx", "-g", "daemon off;"]
- 容器启动时执行的命令
daemon off让 Nginx 在前台运行(Docker 要求)
进阶版本 Dockerfile
# 使用特定版本的 Nginx,提高稳定性
FROM nginx:1.23-alpine
# 设置维护者信息
LABEL maintainer="your-name@example.com"
LABEL description="Custom Nginx Docker Image"
# 设置环境变量
ENV NGINX_PORT=80
ENV NGINX_ROOT=/usr/share/nginx/html
# 安装必要的工具(Alpine Linux 使用 apk)
RUN apk update && apk add --no-cache \
curl \
vim
# 创建自定义配置目录
RUN mkdir -p /etc/nginx/conf.d/custom
# 复制自定义 Nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
# 复制网站文件
COPY html/ /usr/share/nginx/html/
# 设置权限
RUN chown -R nginx:nginx /usr/share/nginx/html
RUN chmod -R 755 /usr/share/nginx/html
# 创建健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# 暴露端口
EXPOSE ${NGINX_PORT}
# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]
构建和运行
项目结构准备
创建以下目录结构:
nginx-docker/
├── Dockerfile
├── nginx.conf
├── default.conf
└── html/
├── index.html
└── style.css
创建配置文件
nginx.conf (基础版本):
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/conf.d/*.conf;
}
default.conf:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ =404;
}
# 健康检查端点
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
html/index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的 Nginx Docker 网站</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>🚀 欢迎使用 Nginx Docker!</h1>
<p>这是一个运行在 Docker 容器中的 Nginx 服务器</p>
<div class="info">
<p><strong>服务器:</strong> Nginx</p>
<p><strong>容器平台:</strong> Docker</p>
<p><strong>状态:</strong> <span class="status">运行中</span></p>
</div>
</div>
</body>
</html>
html/style.css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
background: white;
padding: 3rem;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
text-align: center;
max-width: 500px;
}
h1 {
color: #333;
margin-bottom: 1rem;
}
p {
color: #666;
line-height: 1.6;
margin-bottom: 1rem;
}
.info {
background: #f8f9fa;
padding: 1.5rem;
border-radius: 8px;
margin-top: 1.5rem;
}
.status {
color: #28a745;
font-weight: bold;
}
构建镜像
在项目根目录执行:
# 构建镜像
docker build -t my-nginx .
# 查看构建的镜像
docker images
构建过程详解:
- Docker 读取 Dockerfile
- 下载基础镜像(如果本地没有)
- 按顺序执行每条指令
- 为每个指令创建新的镜像层
- 最终生成完整的镜像
运行容器
# 运行基础版本
docker run -d -p 8080:80 --name my-nginx-container my-nginx
# 运行进阶版本(带健康检查)
docker run -d \
-p 8080:80 \
--name my-nginx-container \
--health-cmd "curl -f http://localhost/health || exit 1" \
--health-interval=30s \
my-nginx
参数解释:
-d:后台运行-p 8080:80:端口映射(主机端口:容器端口)--name:容器名称
验证运行
# 查看运行中的容器
docker ps
# 查看容器日志
docker logs my-nginx-container
# 检查容器健康状态
docker inspect --format='{{.State.Health.Status}}' my-nginx-container
# 访问网站(在浏览器中打开)
# http://localhost:8080
高级配置
使用环境变量
创建支持环境变量的 Dockerfile:
FROM nginx:1.23-alpine
# 设置环境变量默认值
ENV NGINX_PORT=80
ENV NGINX_HOST=localhost
ENV NGINX_ROOT=/usr/share/nginx/html
# 复制可配置的 Nginx 配置模板
COPY nginx.conf.template /etc/nginx/nginx.conf.template
COPY start-nginx.sh /usr/local/bin/
# 安装 envsubst 用于模板替换
RUN apk add --no-cache gettext
# 设置启动脚本权限
RUN chmod +x /usr/local/bin/start-nginx.sh
# 复制静态文件
COPY html/ /usr/share/nginx/html/
EXPOSE ${NGINX_PORT}
# 使用启动脚本
CMD ["/usr/local/bin/start-nginx.sh"]
start-nginx.sh:
#!/bin/sh
# 使用 envsubst 替换环境变量
envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
# 启动 Nginx
exec nginx -g 'daemon off;'
运行带环境变量的容器:
docker run -d \
-p 8080:80 \
-e NGINX_PORT=80 \
-e NGINX_HOST=localhost \
--name my-nginx \
my-nginx
使用多阶段构建
# 构建阶段
FROM node:16-alpine as build-stage
WORKDIR /app
# 复制 package.json 并安装依赖
COPY package*.json ./
RUN npm install
# 复制源码并构建
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:1.23-alpine as production-stage
# 复制构建产物到 Nginx
COPY --from=build-stage /app/dist /usr/share/nginx/html
# 复制自定义配置
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
最佳实践
1. 安全性
# 使用非 root 用户
FROM nginx:1.23-alpine
# 创建非 root 用户(如果基础镜像没有)
RUN addgroup -g 1000 -S nginx-user && \
adduser -S -D -H -u 1000 -h /var/cache/nginx -s /sbin/nologin -G nginx-user -g nginx-user nginx-user
# 更改文件所有权
RUN chown -R nginx-user:nginx-user /usr/share/nginx/html
# 使用非 root 用户运行
USER nginx-user
2. 优化镜像大小
# 使用 Alpine Linux 版本
FROM nginx:1.23-alpine
# 清理缓存
RUN apk update && apk upgrade && \
rm -rf /var/cache/apk/*
# 使用多阶段构建减少最终镜像大小
3. 性能优化
FROM nginx:1.23-alpine
# 优化 Nginx 配置
RUN echo "worker_processes auto;" > /etc/nginx/nginx.conf && \
echo "events { worker_connections 1024; }" >> /etc/nginx/nginx.conf && \
echo "http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; }" >> /etc/nginx/nginx.conf
常用命令备忘
# 构建镜像
docker build -t my-nginx .
# 运行容器
docker run -d -p 8080:80 --name nginx-container my-nginx
# 查看日志
docker logs nginx-container
# 进入容器
docker exec -it nginx-container sh
# 停止容器
docker stop nginx-container
# 删除容器
docker rm nginx-container
# 删除镜像
docker rmi my-nginx
# 查看资源使用
docker stats nginx-container
# 保存镜像到文件
docker save -o my-nginx.tar my-nginx
# 从文件加载镜像
docker load -i my-nginx.tar
故障排除
常见问题及解决方案:
-
端口被占用
# 查看端口占用 netstat -tulpn | grep 8080 # 或者使用其他端口 docker run -d -p 8081:80 --name nginx-container my-nginx -
权限问题
# 在 Dockerfile 中确保文件权限正确 RUN chmod -R 755 /usr/share/nginx/html -
配置文件错误
# 检查 Nginx 配置 docker exec nginx-container nginx -t -
容器启动失败
# 查看详细日志 docker logs nginx-container
总结
通过这个完整的学习文档,你应该已经掌握了:
- ✅ Docker 和 Nginx 的基本概念
- ✅ Dockerfile 的编写和理解
- ✅ 如何构建自定义 Nginx 镜像
- ✅ 容器的运行和管理
- ✅ 高级配置和最佳实践
浙公网安备 33010602011771号