Jerry's Blog

Recording what I learned everyday

View on GitHub


1 May 2021

Docker 4 -- Docker Compose项目示例visits

by Jerry Zhang

创建nodejs项目

创建一个package.json文件

{
    "dependencies": {
        "express": "*",
        "redis": "2.8.0"
    },
    "scripts": {
        "start": "node index.js"
    }
}

创建index.js文件

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient({
    host: 'redis-server',
    port: 6379
});
client.set('visits', 0);

app.get('/', (req, res) => {
    client.get('visits', (err, visits) => {
        res.send('Number of visits is ' + visits);
        client.set('visits', parseInt(visits) + 1);
    });
});

app.listen(8081, () => {
    console.log('Listening on port 8081');
});

创建Dockerfile

FROM node:alpine

WORKDIR '/app'

COPY package.json .
RUN npm install
COPY . .

CMD ["npm", "start"]

此时,运行命令

docker build -t jerry4013/visits .

即可构建这个docker image

不同容器之间的沟通问题

image 构建成功后,如果我们运行这个容器:

docker run jerry4013/visits

会报错,无法连接redis。

那如果我们再另外运行一个redis容器行不行呢?

docker run redis

也会报同样的错。这是由于两个容器之间,是完全隔离的。它们之间无法直接沟通。因此我们需要给它们之间建立网络连接。

Docker Compose

使用Docker Compose可以非常方便地同时运行多个容器,并且使它们之间自动建立连接,互相沟通。

docker compose 是随着docker一起安装好的。在命令行中输入docker-compose即可显示所有相关命令。

创建一个docker-compose.yml文件

version: '3'
services: 
  redis-server:
    image: 'redis'
  node-app:
    build: .
    ports: 
      - "4001:8081"

现在我们希望要让node-app中的redis client能与redis-server沟通,只需要在js代码中,给redis client指定一个host。

const client = redis.createClient({
    host: 'redis-server',
    port: 6379
});

通常来说,这个host是一个真实的主机名,比如https://***,但在这里,我们只需要根据docker-compose.yml文件中的service名称,来指定host,就能找到想要的container。

启动/停止Docker Compose

启动所有容器:

docker-compose up

编译并启动所有容器:

docker-compose up --build

以前,我们想在后台运行某个容器,只需要加个-d,比如:

docker run -d redis

类似地,如果我们用docker-compose来启动多个容器,只需要加个-d,比如:

docker-compose up -d

停止全部容器:

docker-compose down

自动重启

为了测试自动重启功能,我们在index.js代码中加入一些故意使它崩溃的代码。

const process = require('process');

app.get('/', (req, res) => {
    process.exit(0);
    client.get('visits', (err, visits) => {
        res.send('Number of visits is ' + visits);
        client.set('visits', parseInt(visits) + 1);
    });
});

此时,我们重新编译并启动这两个容器:

docker-compose up --build

这时,docker ps可以看到有两个容器正在运行。然后打开浏览器,输入http://localhost:4001/,就可以发现页面崩溃了。然后再用docker ps可以看到,只剩下redis一个容器了。那么,如何才让能这个容器在崩溃后自动重启呢?

错误状态码

exit(0) 代表正常退出。其他数字代表出了错误。

重启策略Restart policies

比如:

version: '3'
services: 
  redis-server:
    image: 'redis'
  node-app:
    restart: always
    build: .
    ports: 
      - "4001:8081"

注意,如果要输入”no”,必须加引号,因为在yml文件中,no 表示false。其实”no”是默认值,不需要写的。

查看docker-compose的容器状态

docker-compose ps

注意,这个命令必须在包含docker-compose.yml的文件夹中使用。

tags: Docker