Docker和TypeScript:从零开始的应用程序容器化
容器化已成为现代开发的标准。Docker允许将TypeScript应用程序及其所有依赖项和环境打包在一起,确保其在任何平台上稳定运行——从开发者的本地计算机到生产服务器。在本文中,我们将介绍完整的流程:从基本的Dockerfile到优化的生产构建。
1. TypeScript开发者的Docker基础
Docker是一个用于在隔离环境(容器)中创建、交付和运行应用程序的平台。对于编译为JavaScript并在Node.js上运行的TypeScript应用程序,Docker解决了三个关键问题:
- 环境可重现性:忘记“在我机器上能运行”这句话。Node.js、npm和系统包的版本在镜像中是固定的。
- 隔离性:每个应用程序在自己的容器中运行,不会影响其他服务。
- 可扩展性:容器易于复制和编排。
开始之前,请确保您已安装Docker和Docker Compose。可以通过以下命令检查:
docker --versiondocker-compose --version2. 为TypeScript应用程序创建Dockerfile
让我们从一个简单的TypeScript应用程序开始。假设我们有一个文件 src/index.ts:
import express from 'express';
const app = express();const port = process.env.PORT || 3000;
app.get('/', (req, res) => { res.send('Hello from Docker + TypeScript!');});
app.listen(port, () => { console.log(`Server started on port ${port}`);});现在在项目根目录创建 Dockerfile:
# ---- 开发基础镜像 ----FROM node:18-alpine AS baseWORKDIR /appCOPY package*.json ./RUN npm ci --only=production
# ---- TypeScript构建 ----FROM base AS buildCOPY tsconfig.json ./COPY src/ ./src/RUN npm ci && npm run build
# ---- 生产镜像 ----FROM node:18-alpine AS productionWORKDIR /appCOPY --from=build /app/dist ./distCOPY --from=base /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/index.js"]这是多阶段构建(multi-stage build)。它允许:
- 仅在构建阶段安装所有依赖项(包括devDependencies)
- 最终镜像中只包含编译后的JavaScript和生产依赖项
- 镜像大小减少2-3倍
构建镜像并启动容器:
docker build -t my-typescript-app .docker run -p 3000:3000 my-typescript-app3. 为开发和配置docker-compose
Docker Compose简化了多容器应用程序的管理。创建 docker-compose.yml:
version: '3.8'
services: app: build: context: . target: development ports: - "3000:3000" volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development command: npm run dev
# 生产版本 app-prod: build: context: . target: production ports: - "80:3000" environment: - NODE_ENV=production为了方便,添加一个单独的开发Dockerfile(可以扩展基础镜像):
# Dockerfile.devFROM node:18-alpineWORKDIR /appCOPY package*.json ./RUN npm installCOPY . .EXPOSE 3000CMD ["npm", "run", "dev"]以开发模式启动:
docker-compose up app得益于 volumes,代码更改会立即生效(热重载),而 /app/node_modules 被排除,以避免覆盖容器中的依赖项。