这里面两个技术是基于我的一个 dechat_docker 技术, 可以在 https://github.com/yantze/dechat_docker 找到。

Docker 容器互联

搭建 docker 服务,一般数据库和服务要分开最好,方便部署和扩展。我用了 Dockerfile 构建了一个 node-server 容器,另外外连 mysql,这是一般情况都会做的事情。

但因为写多个 Dockerfile 太麻烦,我直接用 docker-compose.yaml 写了一个自动初始化 mysql 官方镜像的 service,所以需要用到 node-server 里面的数据库 schema 文件。于是要用到容器互联的方法,下面是我写的一个 docker-compose.yaml 文件:

version: '2'

services:
    node-server:
        # build: ./node-server
        image: yantze/dechat-server:latest
        ports:
            - 2020:2020
        depends_on:
            - mysql-server
        environment:
            DB_HOST: mysql-server
            DB_USER: 'root'
            DB_PWD: 'dechat_AJTYU1'
        restart: always
        volumes:
            - db-schema:/app/design
            - ./tools:/tools
        command: ["/tools/wait-for-it.sh", "mysql-server:3306", "--", "npm", "run", "server"]

    mysql-server:
        image: mariadb
        volumes:
            - ./mariadb-data:/var/lib/mysql:rw
            # innode 问题,ro 最好
            - db-schema:/docker-entrypoint-initdb.d:ro
        environment:
            # MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
            MYSQL_ROOT_PASSWORD: 'dechat_AJTYU1'

volumes:
    db-schema:

这里的 volumes: 块就是指定要共享 volume 的名称。然后在 services: 块里面添加 volumes,一般情况下,类似代码里面的 ./mariadb-data:/var/lib/mysql:rw 这种,有 ./ 或者 / 或者 ~/ 这种指定了绝对路径或者相对路径的,都是把宿主机 mount 到容器中, 如果只是一个名称,就是指定一个共享容器。

在这段代码里面,node-server 会把自己的 /app/design mount 到 db-schema ,于是 mysql-server 能访问到 /app/design 的内容,并且对 /app/design 里面的 sql 文件进行初始化。

另外,由于 mysql 初始化要一段时间,可以用 wait-for-it.sh 等到 mysql 启动完成后,再启动服务器。只需要在docker-compose.yaml中添加 command 命令就好,这个会覆盖 Dockerfile 中的CMD 命令。

自动构建

dechat_docker 项目是下面的结构:

├── docker-compose.yaml
├── node-server
│   └── Dockerfile
└── readme.md

一般情况下,Dockerfile 是放在原生项目里面,但试过后发现暂时不需要,现在统一管理会方便一点。因为需要管理 docker-compose.yaml 文件,方便统一编辑。

使用 docker cloud 自动编译的时候,一般是一旦 git push 后,自动构建 node-server,但是现在用独立的 repo,就会使得自动构建失效,于是可以在构建页面添加触发器。然后把触发器放在 github 或者 bitbucket 中的 Webhooks,一旦原来的项目发生了一次推送,就自动构建。

在构建的时候,一般在本地构建的命令是 docker build -t yantze/dechat-server:v1 .,这里最后的 . 是构建情景的上下文,所以要把 node-server 指定为上下文,否则有可能会把 node-server 文件夹之外的内容复制到容器中(取决于 Dockerfile 怎么写)

Reference & Resource

  • https://docs.docker.com/compose/startup-order/
  • https://docs.docker.com/compose/compose-file/#volume-configuration-reference