nest js docker 化全流程

前置知识点:

Dockerfile: Dockerfile需要先了解

docker-compose: docker-componse 需要先了解

1. 创建Dockerfile

采用多阶段构建方式,包含构建阶段和运行阶段:

  • 构建阶段:安装所有依赖并构建项目
  • 运行阶段:仅安装生产依赖,复制构建产物
  • 暴露3000端口,配置容器启动命令
ts 复制代码
# 构建阶段
# 构建阶段
FROM node:20-alpine AS builder

WORKDIR /app

# 复制package.json和package-lock.json
COPY package*.json ./

# 安装依赖
RUN npm ci

# 复制源代码
COPY . .

# 构建项目
RUN npm run build

# 运行阶段
FROM node:20-alpine AS runner

WORKDIR /app

# 复制package.json和package-lock.json
COPY package*.json ./

# 安装生产依赖
RUN npm ci --only=production

# 复制构建产物
COPY --from=builder /app/dist ./dist

# 复制GraphQL类型定义文件
COPY src/graphql ./src/graphql

# 复制环境变量示例文件(如果有)
COPY .env.development ./.env

# 暴露端口
EXPOSE 3000

# 运行应用
CMD ["node", "dist/main"]

2. 创建docker-compose.yml

配置了完整的服务栈:

  • 应用服务:使用构建的Docker镜像
  • MySQL数据库:版本8.0,配置持久化卷
  • Redis服务:版本7.0-alpine,配置持久化卷
  • 所有服务通过Docker网络连接
ts 复制代码
version: '3.8'

services:
  app:
    build: .
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - PORT=3000
      - DB_HOST=host.docker.internal
      - DB_PORT=3306
      - DB_USER=root
      - DB_PASSWORD=123456
      - DB_NAME=care_of_children
      - REDIS_HOST=host.docker.internal
      - REDIS_PORT=6379
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

3. 创建.dockerignore

忽略不必要的文件和目录,加快构建速度:

  • 依赖目录(node_modules)
  • 构建产物(dist)
  • 日志目录(logs)
  • 环境变量文件(.env)
  • SQL文件和图片文件
ts 复制代码
# 依赖目录
node_modules/

# 构建输出目录
dist/

# 日志目录
logs/

# 环境变量文件(只保留示例文件)
.env
.env.local
.env.*.local

# IDE配置
.vscode/
.idea/

# 测试文件
test/

# 操作系统文件
.DS_Store
Thumbs.db

# 包管理器锁文件(可选,根据需要)
# package-lock.json
# yarn.lock
# pnpm-lock.yaml

# SQL文件
*.sql

# 图片文件
*.png
*.jpg
*.jpeg
*.gif

4. 测试与优化

  • 成功构建Docker镜像
  • 解决了容器启动问题(移除了对cross-env的依赖)
  • 确保应用能正常运行

使用方法

  1. 构建镜像 :docker build -t care-of-children-server .
  2. 运行单个容器 :docker run -p 3000:3000 care-of-children-server
  3. 启动完整服务栈 :docker-compose up

通过以上配置,您的NestJS项目已成功Docker化,可以在任何支持Docker的环境中轻松部署和运行。

以下是我遇到的问题

1. 发现端口映射问题

通过 docker ps 命令发现,之前的应用容器没有正确的端口映射 配置,只有 3000/tcp(内部端口),没有映射到物理机的端口(如 0.0.0.0:3000->3000/tcp)。

2. 解决端口冲突

发现 MySQL (3306端口) 和 Redis (6379端口) 已经在物理机上运行(容器名为 sweet_blackburn 和 redis),导致 docker-compose 尝试启动新实例时出现端口冲突。

3. 修改 docker-compose.yml
  • 移除了内部服务:删除了 docker-compose.yml 中的 MySQL 和 Redis 服务配置
  • 更新环境变量 :将 DB_HOST 和 REDIS_HOST 改为 host.docker.internal,让容器连接到物理机上已运行的数据库和Redis服务
  • 保留端口映射 :确保应用容器的 3000:3000 端口映射配置正确
4. 配置应用监听地址

修改了 src/main.ts 文件,让 NestJS 应用监听 0.0.0.0 地址:

typescript 复制代码
await app.listen(process.env.PORT ?? 3000, '0.0.0.0');

这确保应用接受来自所有网络接口的连接,而不仅仅是容器内部。

5. 重新启动应用容器

使用 docker-compose up -d 重新启动应用容器,确保所有配置生效。

最终结果

现在应用容器正确映射了端口(0.0.0.0:3000->3000/tcp),并且能够:

  • 通过 http://localhost:3000 从物理机访问
  • 连接到物理机上已运行的 MySQL 和 Redis 服务
  • 提供 Swagger API 文档(http://localhost:3000/api)和 GraphQL Playground(http://localhost:3000/graphql)

核心原理

容器与物理机通信的关键在于:

  • 端口映射:将容器端口暴露到物理机
  • 监听地址 :应用必须监听 0.0.0.0 而非仅 localhost
  • 服务连接 :使用 host.docker.internal 让容器访问物理机上的服务
相关推荐
_冷眸_6 分钟前
Python 调用大模型 API:最小请求、Base URL 和 401/404 排查
开发语言·人工智能·python
niucloud-admin17 分钟前
NIUCLOUD PHP SAAS上门家政使用文档:服务保障
java·开发语言·php
熊猫钓鱼>_>43 分钟前
鸿蒙 PC 三方库适配复盘:libfvad 1.0 —— 把 WebRTC VAD 做成能装进采集链路的静态库
服务器·开发语言·华为·harmonyos·openharmony·适配·鸿蒙pc
java_logo1 小时前
Docker 部署 DPanel:轻松搭建轻量容器管理平台
运维·docker·容器·podman·容器管理·dpanel·轩辕镜像
Ai-_Man1 小时前
Coze扣子还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·1024程序员节
死磕音视频1 小时前
Open WebUI 入门:用 Docker 装上本地对话界面并连接 Ollama
docker·ollama·本地大模型·open webui
raindayinrain1 小时前
c++设计模式
开发语言·c++·设计模式
分布式存储与RustFS1 小时前
CI 老被 Docker Hub 的 429 卡住,自建 Registry 把镜像搬进内网
运维·docker·开源·镜像仓库·对象存储·ci·rustfs
hiahiahia1231 小时前
Streaming Model Output
开发语言·前端
paopaokaka_luck1 小时前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts