docker应用
docker+nginx多阶段构建自动化部署
- 1、在项目的根目录创建 Dockerfile 的文件,在其中定义多个构建阶段
- 2、在项目根目录下执行命令构建Docker镜像
- 3、运行Docker容器
相关命令
- 通过localhost:8080 就可以访问容器内运行的nginx服务
# 构建Docker镜像
docker build -t your-image-name .
# 查看是否存在构建好的镜像
docker image ls
# 运行Docker镜像 -d: 后台运行 -p 端口映射(将宿主的8080端口映射到容器的80端口)
docker run -d -p 8080:80 your-image-name
# 查看正在运行的容器
docker ps
多阶段构建
- 第一阶段:构建前端项目,安装依赖、构建打包
- 第二阶段:使用nginx项目,把构建的包dist包复制到Nginx的默认静态文件目录, 开放端口以能够访问这个项目
Dockerfile文件
# 第一阶段:构建前端项目
FROM node:14 as build-stage
# 将此目录作为工作目录(目标目录)
WORKDIR /app
# 复制本目录下的package文件(源文件)到工作目录(目标目录)
COPY package*.json ./
# 安装依赖
RUN npm install
# 将本本录下所有文件复制到目标目录
COPY . .
# 打包构建
RUN npm run build
# 第二阶段:使用 Nginx 镜像
FROM nginx:latest
# 把构建的包dist包复制到Nginx的默认静态文件目录
COPY --from=build-stage /app/dist/ /usr/share/nginx/html
# 暴露端口号
EXPOSE 80
# 是nginx在后台允许
CMD ["nginx", "-g", "daemon off;"]
Nuxt + docker部署实战
Nuxt3部署
- Nuxt 3 + pnpm + pm2 + nginx + Docker Compose 项目
- 定义nuxt服务(启动node)、nginx服务(转发、代理配置)
| 文件 / 文件夹 | 用途 |
|---|---|
Dockerfile | 构建 Nuxt + pm2 运行环境 |
ecosystem.config.js | pm2 启动配置 |
docker-compose.yml | 启动 nuxt 服务 + nginx 服务 |
nginx/default.conf | Nginx 转发配置 |
.dockerignore | 忽略不需要进入镜像的文件 |
pnpm-lock.yaml | pnpm 依赖锁 |
app.vue / pages/index.vue | 简单 Nuxt 页面示例 |
nuxt.config.ts | Nuxt 配置 |
ecosystem.config.cjs
// pm2 start ecosystem.config.cjs --name demo
module.exports = {
apps: [
{
name: 'demo',
port: '3000',
exec_mode: 'cluster',
instances: 'max',
script: './.output/server/index.mjs',
ignore_watch: ['node_modules', '.nuxt', '.output'],
env: {
NODE_ENV: 'production',
},
},
],
}
Dockerfile
# 第1阶段:构建镜像 (指定node基础镜像)
FROM node:20-alpine as build
# (设置工作目录) 设置容器中的工作目录为 /app,之后的命令都会在这个目录中运行。
WORKDIR /app
# (复制文件) 将当前目录下的所有文件复制到容器中的 /app 目录 (格式是 "当前目录:容器目录路径")
COPY . .
RUN npm install -g pnpm
RUN pnpm install
RUN pnpm build
# 第2阶段:部署运行
FROM node:20-alpine
WORKDIR /app
# (复制文件) 将第1阶段构建的输出文件复制到容器中的 /app 目录 (格式是 "当前目录:容器目录路径")
COPY --from=build /app/.output ./.output
COPY --from=build /app/ecosystem.config.cjs ./
# (运行脚本安装PM2) 用于启动node服务
RUN npm install -g pm2
# 暴露容器端口3000
EXPOSE 3000
# (指定Nuxt服务监听地址) 通常 Nuxt 会监听 localhost,这里强制监听 0.0.0.0 以便外部访问
ENV HOST=0.0.0.0
# (指定Nuxt服务监听端口) 应用监听的端口, 设置Node服务的PORT环境变量为3000
ENV PORT=3000
# (启动应用) 使用 PM2 启动 Nuxt 应用 (pm2-runtime是Docker运行PM2方式)
CMD ["pm2-runtime", "start", "ecosystem.config.cjs"]
docker-compose.yml
# 使用 Docker Compose 的 v3 版本语法
version: '3'
# 定义服务
services:
# (服务名称) 定义nuxt-app服务
nuxt-app:
# 使用当前目录下的 Dockerfile 构建镜像
build: .
# 指定容器名为 my-nuxt,便于识别和管理
container_name: my-nuxt
# 将宿主机的 3000 端口映射到容器的 3000 端口。 (格式是 "本机端口:容器端口")
ports:
- "3000:3000"
# 设置环境变量 (Node.js运行环境变量 => production => 启用压缩、缓存、关闭热更新、提高性能)
environment:
- NODE_ENV=production
# 挂载日志目录, 实现日志持久化 (格式是 "本机目录:容器目录")
volumes:
- ./logs:/app/logs
# 设置重启策略
restart: always
# 设置网络
networks:
- app-network
# 定义网络
networks:
# 定义网络名称为 app-network
app-network:
driver: bridge
启动服务
# 构建并启动容器
docker-compose up -d --build
# 构建成功之后访问
http://127.0.0.1:3000
集成nginx服务
本地不需要安装nginx,只需要在docker中集成nginx服务,nginx运行在容器内部的,docker会去拉取nginx的镜像
- 为了扩展,有些项目需要转发路径和配置代理
- 如希望访问 www.demo.com/ads.txt 当访问
ads.txt转发到其他目录中 - 实现了代理转发这样就不需要把所有文件目录都配置在当前项目中,可以分发在不同项目目录
- 如希望访问 www.demo.com/ads.txt 当访问
# 进入nginx容器中的终端
docker exec -it my-nginx sh
nginx.conf
- 这样通过
127.0.0.1就能访问nuxt服务了
# 必须块。虽然这里没有配置内容,但 Nginx 要求必须有 events 块。
events {}
# http:开启 HTTP 服务配置
http {
server {
listen 80;
location / {
# nuxt-app 是 Docker Compose 中定义的服务名,相当于容器内的DNS名
proxy_pass http://nuxt-app: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;
}
}
}
docker-compose.yml
- 增加了nginx服务
# 使用 Docker Compose 的 v3 版本语法
version: '3'
# 定义服务
services:
# (服务名称) 定义nuxt-app服务
nuxt-app:
# 使用当前目录下的 Dockerfile 构建镜像
build: .
# 指定容器名为 my-nuxt,便于识别和管理
container_name: my-nuxt
# 将宿主机的 3000 端口映射到容器的 3000 端口。 (格式是 "本机端口:容器端口")
ports:
- "3000:3000"
# 设置环境变量 (Node.js运行环境变量 => production => 启用压缩、缓存、关闭热更新、提高性能)
environment:
- NODE_ENV=production
# 挂载日志目录, 实现日志持久化 (格式是 "本机目录:容器目录")
volumes:
- ./logs:/app/logs
# 设置重启策略
restart: always
# 设置网络
networks:
- app-network
nginx:
image: nginx:alpine
container_name: my-nginx
ports:
- "80:80" # 宿主机80端口映射到nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- nuxt-app
networks:
- app-network
# 定义网络
networks:
# 定义网络名称为 app-network
app-network:
driver: bridge
配置nginx资源路径映射
在 Nginx 中,root 和 alias 都可以用于静态资源的路径映射
- 当访问其他资源的时候,通过nginx可以转发指向到指定的目录
- 1、访问
http://127.0.0.1/demo.txt转发到访问容器内的其他目录 - 2、挂载静态文件到 Nginx 容器
- 在 docker-compose.yml 的 nginx 服务下添加volumes卷
- 把本地(服务器)上的目录资源挂载到容器指定的目录中
- 3、当挂载后,nginx.conf 的 alias、root转发配置才会生效
检查nginx容器,是否有挂载的文件
# 进入nginx容器终端
docker exec -it my-nginx sh
# app/static是挂载的目录
ls /app/static/
每次修改nginx的配置,都需要重启nginx容器
docker restart my-nginx
nginx.conf
- 配置转发
- 使用
root或者alias来配置目录的指向 - 使用$uri来匹配请求的路径,如
127.0.0.1/demo.html, 则请求的路径为/demo.html
# 必须块。虽然这里没有配置内容,但 Nginx 要求必须有 events 块。
events {}
# http:开启 HTTP 服务配置
http {
server {
listen 80;
# 代理转发(具体某文件目录) 当访问127.0.0.1/demo.txt 时,会代理转发到 /app/static/demo.txt
location = /demo.txt {
alias /app/static/demo.txt;
}
# 代理转发(匹配更多文件,如以html后缀结尾的文件) $uri 是 Nginx 的内置变量,代表当前请求的 URI 路径
location ~ \.html$ {
alias /app/static$uri;
}
location / {
# nuxt-app 是 Docker Compose 中定义的服务名,相当于容器内的DNS名
proxy_pass http://nuxt-app: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;
}
}
}
docker-compose.yaml
- 核心nginx服务的volumes目录挂载配置
- 把本地服务器的目录挂载到nginx容器目录中
# 使用 Docker Compose 的 v3 版本语法
version: '3'
# 定义服务
services:
# (服务名称) 定义nuxt-app服务
nuxt-app:
# 使用当前目录下的 Dockerfile 构建镜像
build: .
# 指定容器名为 my-nuxt,便于识别和管理
container_name: my-nuxt
# 将宿主机的 3000 端口映射到容器的 3000 端口。 (格式是 "本机端口:容器端口")
ports:
- "3000:3000"
# 设置环境变量 (Node.js运行环境变量 => production => 启用压缩、缓存、关闭热更新、提高性能)
environment:
- NODE_ENV=production
# 挂载日志目录, 实现日志持久化 (格式是 "本机目录:容器目录")
volumes:
- ./logs:/app/logs
# 设置重启策略
restart: always
# 设置网络
networks:
- app-network
nginx:
image: nginx:alpine
container_name: my-nginx
ports:
- "80:80" # 宿主机80端口映射到nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
# 本地路径 d:/a-frontEnd/my-test/static
# 挂载目录 d:/a-frontEnd/my-test/static 到容器内 /app/static
- /d/a-frontEnd/my-test/static:/app/static
depends_on:
- nuxt-app
networks:
- app-network
# 定义网络
networks:
# 定义网络名称为 app-network
app-network:
driver: bridge