Docker 和 Docker Compose
Docker 允许开发人员将他们的应用程序与所有依赖项一起打包到一个称为容器的单个单元中。这确保了在不同环境(如开发、测试和生产环境)之间的一致性,从而缓解了“它在我的机器上能跑”的问题。
安装 Docker:https://docs.docker.com/engine/install/
Dockerfile
Dockerfile 是一个包含构建 Docker 镜像指令的文本文件。它定义了创建 Docker 镜像所需的步骤,作为将来启动 Docker 容器的蓝图。
添加 Dockerfile:
# Use the official Node.js image with specified version
FROM node:20.11-alpine3.18
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json to the working directory
COPY package*.json ./
# Install project dependencies
RUN npm install
# Copy the source code to the working directory
COPY src/ /usr/src/app/src
COPY tsconfig.json ./
# Build TypeScript code
RUN npm run build
# Expose the required ports
EXPOSE 3000
# Command to run the application
CMD ["node", "dist/main.js"]
Alpine Linux 是一个轻量级的安全的 Linux 发行版,特别适用于容器化环境、嵌入式系统和资源受限环境。这些环境下效率和安全性至关重要。
构建你的 docker 镜像:
docker build . -t lrbooks-nodejs:latest
注意:
如果遇到权限问题,使用sudo docker ...
。
执行 docker images
来检查镜像:
docker images
结果:
REPOSITORY TAG IMAGE ID CREATED SIZE
lrbooks-nodejs latest 47e247df12a8 46 seconds ago 215MB
...
Docker Compose
Docker Compose 是一个用于定义和运行多容器的 Docker 工具。它允许你使用 YAML 文件配置应用程序的服务、网络和卷,然后使用单个命令启动所有运行所需的容器,包括应用程序的依赖中间件和服务。
注意:
安装 Docker Compose 最方便最推荐的方式是安装 Docker 桌面版。Docker 桌面版包含了 Docker 引擎,Docker CLI 和 Docker Compose。
按需安装 Compose:https://docs.docker.com/compose/install/
添加 compose/docker-compose.yml:
services:
lr-rest-books:
image: lrbooks-nodejs:latest
ports:
- 3000:3000
volumes:
- ./config.json:/usr/src/app/config.json
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
mongo:
condition: service_started
redis:
image: docker.io/bitnami/redis:7.0
environment:
- REDIS_PASSWORD=${REDIS_PASSWORD}
ports:
- 6379:6379
mysql:
image: docker.io/bitnami/mysql:5.7.43
environment:
- MYSQL_DATABASE=lr_book
- MYSQL_USER=test_user
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
ports:
- 3306:3306
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
volumes:
- ~/lr-mysql-data:/bitnami/mysql/data
mongo:
image: bitnami/mongodb:latest
environment:
- ALLOW_EMPTY_PASSWORD=yes
ports:
- 27017:27017
volumes:
- ~/lr-mongodb-data:/bitnami/mongodb
添加专用于 Compose 的配置文件,compose/config.json:
{
"app": {
"port": 3000,
"page_size": 5,
"token_secret": "LiteRank_in_Compose",
"token_hours": 48
},
"db": {
"file_name": "test.db",
"dsn": "mysql://test_user:test_pass@mysql:3306/lr_book?charset=utf8mb4",
"mongo_uri": "mongodb://mongo:27017",
"mongo_db_name": "lr_book"
},
"cache": {
"host": "redis",
"port": 6379,
"password": "test_pass",
"db": 0,
"timeout": 5000
}
}
添加 compose/.env 用于设置环境变量:
REDIS_PASSWORD=test_pass
MYSQL_PASSWORD=test_pass
MYSQL_ROOT_PASSWORD=test_root_pass
警告:
.env
文件应该在.gitignore
中添加以告知 git 忽略该文件。
更改 .gitignore:
test.db
+.env
执行:
cd compose
docker compose up
你应该看到类似下方内容:
[+] Running 4/4
✔ Container compose-redis-1 Created 0.0s
✔ Container compose-mysql-1 Recreated 0.1s
✔ Container compose-mongo-1 Recreated 0.1s
✔ Container compose-lr-rest-books-1 Recreated 0.0s
Attaching to lr-rest-books-1, mongo-1, mysql-1, redis-1
redis-1 | redis 13:24:52.38
redis-1 | redis 13:24:52.39 Welcome to the Bitnami redis container
...
mongo-1 | mongodb 13:24:52.60 INFO ==>
mongo-1 | mongodb 13:24:52.60 INFO ==> Welcome to the Bitnami mongodb container
mongo-1 | mongodb 13:24:52.61 INFO ==> ** Starting MongoDB setup **
...
mysql-1 | mysql 13:24:52.61
mysql-1 | mysql 13:24:52.62 Welcome to the Bitnami mysql container
mysql-1 | mysql 13:24:52.63 INFO ==> ** Starting MySQL setup **
...
你不再需要手动安装那些数据库。它们都被 docker compose 搞定了。
如果你发一些请求到 3000 端口的 api 服务器,你将看到如下日志:
lr-rest-books-1 | ::ffff:192.168.65.1 - - [02/Mar/2024:12:35:11 +0000] "GET /books/4/reviews?q=masterpiece HTTP/1.1" 200 2 "-" "curl/8.1.2" - 19.527 ms
lr-rest-books-1 | ::ffff:192.168.65.1 - - [02/Mar/2024:12:35:21 +0000] "GET /books/2/reviews?q=masterpiece HTTP/1.1" 200 2 "-" "curl/8.1.2" - 3.162 ms
lr-rest-books-1 | ::ffff:192.168.65.1 - - [02/Mar/2024:12:35:26 +0000] "GET /books/2/reviews?q=masterpiece HTTP/1.1" 200 2 "-" "curl/8.1.2" - 2.242 ms
...
如果你想跳过 docker 镜像构建步骤,可以调整 compose/docker-compose.yml:
@@ -1,6 +1,8 @@
services:
lr-rest-books:
- image: lrbooks-nodejs:latest
+ build:
+ context: ../
+ dockerfile: Dockerfile
ports:
- 3000:3000
volumes:
再次运行:
docker compose up
Compose 插件会自动按需构建你的镜像。
[+] Building 3.5s (13/13) FINISHED docker:desktop-linux
=> [lr-rest-books internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 593B 0.0s
=> [lr-rest-books internal] load metadata for docker.io/library/node:20.11-alpine3.18 3.3s
=> [lr-rest-books auth] library/node:pull token for registry-1.docker.io 0.0s
=> [lr-rest-books internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [lr-rest-books 1/7] FROM docker.io/library/node:20.11-alpine3.18@sha256:a02826c7340c37a29179152723190bcc3044f933c925f3c2d78abb20f794de3f 0.0s
=> [lr-rest-books internal] load build context 0.2s
=> => transferring context: 2.21kB 0.2s
=> CACHED [lr-rest-books 2/7] WORKDIR /usr/src/app 0.0s
=> CACHED [lr-rest-books 3/7] COPY package*.json ./ 0.0s
=> CACHED [lr-rest-books 4/7] RUN npm install 0.0s
=> CACHED [lr-rest-books 5/7] COPY src/ /usr/src/app/src 0.0s
=> CACHED [lr-rest-books 6/7] COPY tsconfig.json ./ 0.0s
=> CACHED [lr-rest-books 7/7] RUN npm run build 0.0s
=> [lr-rest-books] exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:fe1c6e9f44aee52d0eb80032cdc1d9c961f2c6c2b18aeed69c763bb3464241f0 0.0s
=> => naming to docker.io/library/compose-lr-rest-books 0.0s
[+] Running 4/4
✔ Container compose-mongo-1 Created 0.0s
✔ Container compose-redis-1 Created 0.0s
✔ Container compose-mysql-1 Created 0.0s
✔ Container compose-lr-rest-books-1 Created 0.1s
Attaching to lr-rest-books-1, mongo-1, mysql-1, redis-1
...
现在,你可以用 curl 再次测试那些端点。它们应该表现得超预期的顺滑。
Kubernetes
如果你的云原生方案想更进一步的话,请尝试 Kubernetes。
它也被称为 K8s,是一个用于自动化部署、扩展和管理容器化应用程序的开源系统。
创建一个如下的部署 yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: lr-books-deployment
spec:
replicas: 3
selector:
matchLabels:
app: lr-books
template:
metadata:
labels:
app: lr-books
spec:
containers:
- name: lr-books-api
image: lrbooks-nodejs:latest
ports:
- containerPort: 3000
然后执行如下命令使其生效:
kubectl apply -f lr-books-deployment.yaml