» Go:使用Gin构建REST API » 3. 部署 » 3.3 Docker与Docker Compose

Docker 与 Docker Compose

Docker 允许开发人员将他们的应用程序与所有依赖项一起打包到一个称为容器的单个单元中。这确保了在不同环境(如开发、测试和生产环境)之间的一致性,从而缓解了“它在我的机器上能跑”的问题。

安装 Docker:https://docs.docker.com/engine/install/

Dockerfile

Dockerfile 是一个包含构建 Docker 镜像指令的文本文件。它定义了创建 Docker 镜像所需的步骤,作为将来启动 Docker 容器的蓝图。

添加 Dockerfile

# alpine linux
FROM alpine:3.19

# Prepare server stuff
ENV APP_BIN=lrbooks
ARG SERVER_DIR=/home/.server
WORKDIR $SERVER_DIR
COPY ./${APP_BIN} .

ENV GIN_MODE=release

CMD ./${APP_BIN}

Alpine Linux 是一个轻量级的安全的 Linux 发行版,特别适用于容器化环境、嵌入式系统和资源受限环境。这些环境下效率和安全性至关重要。

构建一个适用于 Linux 环境的二进制文件:

make build-linux

它等同于 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o lrbooks

构建你的 docker 镜像:

docker build . -t lrbooks:latest

注意
如果遇到权限问题,使用 sudo docker ...

执行 docker images 来检查镜像:

docker images

结果:

REPOSITORY                 TAG       IMAGE ID       CREATED         SIZE
lrbooks                    latest    6ce922011450   2 minutes ago   257MB
...

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:latest
    ports:
      - 8080:8080
    volumes:
      - ./config.yml:/home/.server/config.yml
    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.yml

app:
  port: 8080
  page_size: 10
  token_secret: "LiteRank_in_Compose"
  token_hours: 72
db:
  file_name: "test.db"
  dsn: "test_user:test_pass@tcp(mysql:3306)/lr_book?charset=utf8mb4&parseTime=True&loc=Local"
  mongo_uri: "mongodb://mongo:27017"
  mongo_db_name: "lr_book"
cache:
  address: redis:6379
  password: test_pass
  db: 0
  timeout: 50

添加 compose/.env 用于设置环境变量:

REDIS_PASSWORD=test_pass
MYSQL_PASSWORD=test_pass
MYSQL_ROOT_PASSWORD=test_root_pass

警告.env 文件应该在 .gitignore 中添加以告知 git 忽略该文件。

更改 .gitignore

@@ -22,3 +22,4 @@ go.work
 
 test.db
 lrbooks
+.env

执行:

cd compose
docker compose up

你应该看到类似下方内容:

[+] Running 4/4
 ✔ Container compose-mongo-1          Created                                                                                                                                                                                          0.0s 
 ✔ Container compose-redis-1          Created                                                                                                                                                                                          0.0s 
 ✔ Container compose-mysql-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 搞定了。

如果你发一些请求到 8080 端口的 api 服务器,你将看到如下日志:

lr-rest-books-1  | [GIN] 2024/02/27 - 13:26:09 | 200 |    2.647982ms |    192.168.65.1 | GET      "/books/1/reviews"
lr-rest-books-1  | [GIN] 2024/02/27 - 13:27:15 | 401 |      51.059µs |    192.168.65.1 | POST     "/books"
lr-rest-books-1  | [GIN] 2024/02/27 - 13:27:15 | 401 |      28.097µs |    192.168.65.1 | POST     "/books"
lr-rest-books-1  | [GIN] 2024/02/27 - 13:27:15 | 401 |      25.604µs |    192.168.65.1 | POST     "/books"
...

如果你想跳过 docker 镜像构建步骤,可以调整 compose/docker-compose.yml

@@ -1,6 +1,8 @@
 services:
   lr-rest-books:
-    image: lrbooks:latest
+    build:
+      context: ../
+      dockerfile: Dockerfile
     ports:
       - 8080:8080
     volumes:

再次运行:

docker compose up

Compose 插件会自动按需构建你的镜像。

[+] Building 3.2s (9/9) FINISHED                                                                                                                                                                                       docker:desktop-linux
 => [lr-rest-books internal] load build definition from Dockerfile                                                                                                                                                                     0.0s
 => => transferring dockerfile: 242B                                                                                                                                                                                                   0.0s
 => [lr-rest-books internal] load metadata for docker.io/library/golang:1.22.0-alpine3.19                                                                                                                                              3.1s
 => [lr-rest-books auth] library/golang: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/3] FROM docker.io/library/golang:1.22.0-alpine3.19@sha256:8e96e6cff6a388c2f70f5f662b64120941fcd7d4b89d62fec87520323a316bd9                                                                                        0.0s
 => [lr-rest-books internal] load build context                                                                                                                                                                                        0.0s
 => => transferring context: 31B                                                                                                                                                                                                       0.0s
 => CACHED [lr-rest-books 2/3] WORKDIR /home/.server                                                                                                                                                                                   0.0s
 => CACHED [lr-rest-books 3/3] COPY ./lrbooks .                                                                                                                                                                                        0.0s
 => [lr-rest-books] exporting to image                                                                                                                                                                                                 0.0s
 => => exporting layers                                                                                                                                                                                                                0.0s
 => => writing image sha256:d3fb8b1826bdf8dfe765980ebf2dc754d38c006e64a11feb42c76900d6540ad4                                                                                                                                           0.0s
 => => naming to docker.io/library/compose-lr-rest-books                                                                                                                                                                               0.0s
[+] Running 4/3
 ✔ Container compose-mongo-1          Created                                                                                                                                                                                          0.0s 
 ✔ Container compose-mysql-1          Created                                                                                                                                                                                          0.0s 
 ✔ Container compose-redis-1          Created                                                                                                                                                                                          0.0s 
 ✔ Container compose-lr-rest-books-1  Recreated                                                                                                                                                                                        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:latest
        ports:
        - containerPort: 8080

然后执行如下命令使其生效:

kubectl apply -f lr-books-deployment.yaml