本文将介绍如何通过 Docker 和 Docker Compose,高效地部署一个 Node.js 应用并使其连接到 MySQL 数据库。
项目结构
首先,我们来看一个典型项目的目录结构:
my-node-app/
├── Dockerfile
├── docker-compose.yml
├── package.json
├── server.js
└── .dockerignore
编写 Node.js 应用
以下是 server.js 的简单示例,它使用 Express 框架并连接 MySQL:
const express = require('express');
const mysql = require('mysql2/promise'); // 使用 promise 版本
const app = express();
const port = 3000;
// 从环境变量读取数据库配置
const dbConfig = {
host: process.env.MYSQL_HOST || 'localhost',
user: process.env.MYSQL_USER || 'root',
password: process.env.MYSQL_PASSWORD || 'password',
database: process.env.MYSQL_DATABASE || 'myapp'
};
// 创建数据库连接池
let pool;
async function initDb() {
pool = mysql.createPool(dbConfig);
try {
const connection = await pool.getConnection();
console.log('成功连接到 MySQL 数据库!');
connection.release();
} catch (err) {
console.error('数据库连接失败:', err);
process.exit(1);
}
}
app.get('/', async (req, res) => {
try {
const [rows] = await pool.query('SELECT NOW() as current_time');
res.json({ message: 'Hello from Docker!', time: rows[0].current_time });
} catch (error) {
res.status(500).json({ error: '数据库查询失败' });
}
});
// 初始化并启动服务
initDb().then(() => {
app.listen(port, () => {
console.log(`应用运行在 http://localhost:${port}`);
});
});
相应的 package.json 文件依赖如下:
{
"name": "my-node-app",
"version": "1.0.0",
"description": "A simple Node.js app with MySQL",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.2",
"mysql2": "^3.5.1"
}
}
创建 Dockerfile
接下来,我们编写 Dockerfile 来构建应用镜像:
# 使用官方 Node.js 运行时作为基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /usr/src/app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用源代码
COPY . .
# 暴露应用端口
EXPOSE 3000
# 定义环境变量(可在 docker-compose 中覆盖)
ENV MYSQL_HOST=db
ENV MYSQL_USER=root
ENV MYSQL_PASSWORD=secret
ENV MYSQL_DATABASE=myapp
# 启动命令
CMD [ "node", "server.js" ]
配置 Docker Compose
核心部分在于 docker-compose.yml 文件,它定义了应用服务 (app) 和数据库服务 (db) 及其网络关系:
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- MYSQL_HOST=db # 使用服务名作为主机名
- MYSQL_USER=${MYSQL_USER:-root}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-your_mysql_password}
- MYSQL_DATABASE=${MYSQL_DATABASE:-myapp}
depends_on:
- db
networks:
- app-network
restart: unless-stopped
db:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-your_mysql_root_password}
- MYSQL_DATABASE=${MYSQL_DATABASE:-myapp}
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
restart: unless-stopped
# 可选:自定义配置文件
# command: --default-authentication-plugin=mysql_native_password
networks:
app-network:
driver: bridge
volumes:
mysql-data:
启动与测试
-
启动服务:在项目根目录执行以下命令,Docker Compose 将自动构建应用镜像并启动所有服务。
docker-compose up -d
-
查看日志:可以使用以下命令查看特定服务的日志。
docker-compose logs -f app
-
测试接口:服务启动后,在浏览器中访问 http://localhost:3000,如果返回包含当前数据库时间的 JSON 数据,说明 Node.js 应用已成功连接到 MySQL 数据库。
-
停止服务:运行以下命令停止并移除所有容器、网络(保留数据卷)。
docker-compose down
如需同时移除数据卷,请使用 docker-compose down -v(注意:这将清除所有数据库数据)。
总结
通过以上步骤,我们成功地使用 Docker Compose 编排了一个包含 Node.js 应用和 MySQL 数据库的完整开发环境。这种方法保证了环境的一致性,简化了部署流程,非常适合本地开发和测试。在实际生产环境中,你可能还需要考虑镜像安全、数据备份、服务监控和更复杂的网络配置。