Zero's Blog

多容器应用栈

多容器应用栈

创建一个使用 Express 框架的、带有 Redis 后端的 Node.js 应用,并完全 Docker 化。应用会创建一系列的镜像来部署多容器应用。

  • Nodejs 容器,服务于 Node 应用
  • Redis 容器,用于保存和集群化应用状态,Redis 会有两个备份容器
  • 日志容器,用于捕捉应用日志

Redis 镜像

Redis 基础镜像

构建 Redis 基础镜像,之后会使用基础镜像构建主从 Redis 镜像

1
docker build -t czero/redis .

Redis Dockerfile

构建 Redis 主镜像

1
docker build -t czero/redis-primary .

通过 ENTRYPOINT 指令制定了 Redis 服务的启动命令,Redis 服务的日志文件保存到/var/log/redis/redis-server.log

Redis_primary Dockerfile

构建 Redis 从镜像

1
docker build -t czero/redis_replica .

Redis_replica Dockerfile

创建 Redis 后端集群

构建 Redis 主容器

1
docker run -d -h Redisprimary --name redis_primary czero/redis_primary:latest
  • 使用-h参数用来指定容器的主机名,用来后面从容器正确解析 Redisprimary
  • 使用--name指定容器名

如果想要查看 redis 日志,直接使用docker logs redis_primary 会发现没有任何输出,因为redis把日志输出到日志文件中,可以运行另外一个容器来查看日志

1
2
3
4
5
6
7
8
9
10
11
12
docker run -ti --rm --volumes-from=redis_primary ubuntu:16.04 cat /var/log/redis/redis-server.log
1:M 16 Nov 02:52:25.518 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 16 Nov 02:52:25.518 # Server started, Redis version 3.0.7
1:M 16 Nov 02:52:25.518 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:M 16 Nov 02:52:25.518 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1:M 16 Nov 02:52:25.518 * The server is now ready to accept connections on port 6379
1:M 16 Nov 04:10:50.447 * Slave 172.17.0.3:6379 asks for synchronization
1:M 16 Nov 04:10:50.447 * Full resync requested by slave 172.17.0.3:6379
1:M 16 Nov 04:10:50.447 * Starting BGSAVE for SYNC with target: disk
1:M 16 Nov 04:10:50.448 * Background saving started by pid 9
9:C 16 Nov 04:10:50.478 * DB saved on disk
  • 使用--rm 参数指定的容器,只会运行一次,进程结束之后便会删除
  • 使用--volumes-from=参数指定挂载那个容器的所有卷
  • 后面便是指定使用某个镜像、执行某些命令

构建 Redis 从容器

1
2
docker run -d -h Redisreplica1 --name redis_replica1 --link redis_primary:Redisprimary czero/redis_replica:latest
docker run -d -h Redisreplica2 --name redis_replica2 --link redis_primary:Redisprimary czero/redis_replica:latest
  • 使用-h参数用来指定容器的主机名
  • 使用--name指定容器名
  • 使用--linkredis_primary以别名Redisprimary连接到 Redis 从容器

查看redis_replica的log,看看主从时候正常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run -ti --rm --volumes-from=redis_replica1 ubuntu:16.04 cat /var/log/redis/redis-replica.log
1:S 16 Nov 04:10:50.445 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:S 16 Nov 04:10:50.445 # Server started, Redis version 3.0.7
1:S 16 Nov 04:10:50.445 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:S 16 Nov 04:10:50.445 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1:S 16 Nov 04:10:50.445 * The server is now ready to accept connections on port 6379
1:S 16 Nov 04:10:50.445 * Connecting to MASTER Redisprimary:6379
1:S 16 Nov 04:10:50.446 * MASTER <-> SLAVE sync started
1:S 16 Nov 04:10:50.446 * Non blocking connect for SYNC fired the event.
1:S 16 Nov 04:10:50.446 * Master replied to PING, replication can continue...
1:S 16 Nov 04:10:50.447 * Partial resynchronization not possible (no cached master)
1:S 16 Nov 04:10:50.454 * Full resync from master: 48e2c5daef6f05d3e3d03c074001e301073da55b:1
1:S 16 Nov 04:10:50.545 * MASTER <-> SLAVE sync: receiving 18 bytes from master
1:S 16 Nov 04:10:50.545 * MASTER <-> SLAVE sync: Flushing old data
1:S 16 Nov 04:10:50.545 * MASTER <-> SLAVE sync: Loading DB in memory
1:S 16 Nov 04:10:50.545 * MASTER <-> SLAVE sync: Finished with success

Node.js 镜像

1
2
3
4
5
6
7
8
9
10
tree nodejs
nodejs
├── Dockerfile
└── nodeapp
├── package.json
└── server.js
1 directory, 3 files
docker build -t czero/nodejs .
[Nodejs Dockerfile](http://ofc9x1ccn.bkt.clouddn.com/upload/docker/nodejs.tar.gz)

创建 Node 容器

1
docker run -d --name nodeapp -p 3000:3000 --link redis_primary:Redisprimary czero/nodejs:latest
  • 使用czero/nodejs:latest镜像创建了一个名为 nodeapp 的新容器
  • 使用使用-p 将容器的3000端口映射到宿主机的3000端口
  • 使用--linkredis_primaryRedisprimary作为别名连接到新建的nodeapp容器

查看 Node 应用时候正常

1
2
3
4
curl localhost:3000
{
"status": "ok"
}

Node应用返回OK便表示应用正常,浏览器的会话状态会被记录到Redis主容器redis_primary中,然后便会同步到两个从容器redis_replica1、redis_replica2

捕获应用日志

现在应用已经正常运行,使用logstash来捕获应用日志。

创建 logstash 镜像

1
docker build -t czero/logstash .

Logstash Dockerfile

构建 logstash 容器

1
docker run -d --name logstash --volumes-from=nodeapp --volumes-from=redis_primary czero/logstash
  • 使用两次--volumes-from挂载nodeappredis_primary的卷,用来访问RedisNode的日志
1
2
3
4
5
6
7
8
9
docker logs -f logstash
{
"message" => "::ffff:172.17.0.1 - - [Fri, 18 Nov 2016 08:30:31 GMT] \"GET / HTTP/1.1\" 200 20 \"-\" \"curl/7.47.0\"",
"@version" => "1",
"@timestamp" => "2016-11-18T08:30:31.254Z",
"host" => "98b2284cb329",
"path" => "/var/log/nodeapp/nodeapp.log",
"type" => "syslog"
}

现在 Node 和 Redis 的日志便都输出到 logstash里面了。