0%

今天尝试了一下使用类slack的网页聊天服务:rocket chat.感觉搭建起来还是挺方便的.当然其中也遇到一些坑,所以把最后成功的方式记录下来.

由于rocket chat使用了mongo做存储,所以也需要启动一个mongo的容器.

阅读全文 »

docker启动kafka

最近在做微服务项目,准备使用kafka作为MQ。
自己以前没接触过kafka,所以自己想搭建一个环境,试用一下。

阅读全文 »

Docker容器

当容器以docker run方式运行时,可以给容器添加标签。一个容器在任何一个时刻可以有多个标签。

注意这个例子,我们是在CLI里使用标签,而不是使用自动化工具,所以标签并没有使用DNS标记格式。

单标签

添加单标签需要使用选项l = ,下面的例子会给容器加一个user标签并带有一个ID,这样就可以让我们在所有容器中查找指定的user。

1
docker run -l user=12345 -d redis

外部文件

可以使用外部文件的方式来添加多个标签。外部文件中要没行有一个标签,这些标签会被添加到容器中。

下面的语句会添加2个标签,一个是user一个是role。

1
echo 'user=123461' >> labels && echo 'role=cache' >> labels

选项*-label-file=*会将文件中的每一行设置成容器的标签。

1
docker run --label-file=labels -d redis

Docker镜像

镜像的标签和容器的标签的作用相同,不过镜像的标签是写在Dockerfile中的。当容器加载时,镜像的标签会应用到容器实例上。

单标签

在Dockerfile中可以使用LABEL 指令设置标签。

1
LABEL vendor=Katacoda

多标签

要想设置多标签,使用下面的格式。  (“\“)用来分割。注意使用DNS格式来关联第三方工具。

1
LABEL vendor=Katacoda \ com.katacoda.version=0.0.5 \ com.katacoda.build-date=2016-07-01T10:47:29Z \ com.katacoda.course=Docker

查看详细

标签和元数据仅用来查询或者查看。第一个方法就是用 docker inspect 来查看特定的容器或者镜像。

任务

假设环境中已经有了一个容器叫 rd,和一个镜像叫 katacoda-label-example。

容器

根据容器的名字或者hash id,可以查看容器的全部的元数据。

1
docker inspect rd

使用*-f*选项可以指定显示的JSON结果里仅显示Lable的信息。

1
docker inspect -f "{{json .Config.Labels }}" rd

镜像

查看镜像的Lable与容器的方式一致,但是略有不同。使用ContainerConfig而不是Config

1
docker inspect -f "{{json .ContainerConfig.Labels }}" katacoda-label-example

这些标签会一直存在,即便在镜像被撤掉标签后,撤掉标签后这个信息会是**.(These labels will remain even if the image has been untagged. When an image is untagged, it will have the name .)

根据标签查询

查看容器或者镜像的容器可以提供很多有用的信息,但是在生产环境中上千个容器中,使用标签来限定返回的个数会很有用。

过滤容器

使用 docker ps 可以根据lable来过滤指定容器。下面的例子就是过滤lable是user,值是katacoda的容器。

1
docker ps --filter "label=user=scrapbook"

过滤镜像

使用同样的方式过滤镜像。

1
docker images --filter "label=vendor=Katacoda"

注意

过滤时使用的key和value都是大小写敏感的。

Daemon标签

标签也可以应用于Docker的daemon上。当启动一个daemon实例时,可以指定标签,例如在开发服务器或者生产服务器上,指定daemon的角色会是不错的选择。

再之后我们会探讨更多的关于Docker配置和标签使用的更多内容。这里我们简单看一下格式:

1
2
3
4
docker -d \
-H unix:///var/run/docker.sock \
--label com.katacoda.environment="production" \
--label com.katacoda.storage="ssd"

失败时停止

Docker将容器的非零退出算作容器崩溃。默认情况,容器崩溃后会一直保持停止状态。

我们这里有个特殊的容器,会发送一条消息,然后退出返回1。这就可以模拟一个容器崩溃。

1
docker run -d --name restart-default scrapbook/docker-restart-example

如果列出所有的容器,包括停止的,就会看到这个停用的容器。

1
docker ps -a

可以看log来定位问题

1
docker logs restart-default

失败后重启

根据场景,有可能重启失败的进程就可以解决问题。Docker会自动尝试启动指定次数,直到仍然失败。

命令选项:*–restart=on-failure:#*运行你设置Docker尝试重启的次数。下面的例子,docker会尝试重启3次。

1
docker run -d --name restart-3 --restart=on-failure:3 scrapbook/docker-restart-example

可以查看log,确实重启的3次。

1
docker logs restart-3

一直重启

最后,可以设置Docker一直重启容器。这个例子中,Docker会一直重启容器,直到容器明确告知停止。

使用always标识,在容器崩溃后会一直尝试重启。

1
docker run -d --name restart-always --restart=always scrapbook/docker-restart-example

查看log会看到不断尝试重启的记录

1
docker logs restart-always

Docker Logs

一旦启动容器,Docker会记录进程的标准输出和标准错误,并且使用Docker客户端可以访问。

假设后台有一个Redis实例容器在运行,容器名是redis-server。使用Docker客户端,可以使用如下语句来访问标准输出和标准错误。

1
docker logs redis-server

SysLog

Docker默认使用json格式的log文件存储在主机上。这会在硬盘上存储大量的文件,可以把Log文件存储到其他的目标位置。

The Syslog log driver will write all the container logs to the central syslog on the host. “syslog is a widely used standard for message logging. It permits separation of the software that generates messages, the system that stores them, and the software that reports and analyses them.” Wikipedia

This log-driver is designed to be used when syslog is being collected and aggregated by an external system.

使用下面的语句可以把Redis的Log记录进syslog

1
docker run -d --name redis-syslog --log-driver=syslog redis

如果尝试用客户端访问这些Log,会出现错误:FATA[0000] “logs” command is supported only for “json-file” logging driver

应该使用syslog 流来访问。

停用记录日志

当容器日志很冗长的时候可以停用日志。

将log-driver设置成none即可以停用日志。

1
docker run -d --name redis-none --log-driver=none redis

inspect命令可以查看某个容器的Log配置。下面的命令会输出每个容器Log配置的部分。

1
2
3
4
5
docker inspect --format '{{ .HostConfig.LogConfig }}' redis-server

docker inspect --format '{{ .HostConfig.LogConfig }}' redis-syslog

docker inspect --format '{{ .HostConfig.LogConfig }}' redis-none

数据卷

宿主机的*/docker/redis-data*目录映射到容器的 /data目录

1
2
3
docker run  -v /docker/redis-data:/data \
--name r1 -d redis \
redis-server --appendonly yes

使用下面的语句可以向Redis实例中pipe数据

1
cat data | docker exec -i r1 redis-cli --pipe

在主机上可以查看映射的目录里有Redis的数据文件。

1
ls /docker/redis-data

同样的文件还可以挂在到第二个容器。其中一个应用就是用docker容器起到数据备份的作用。

1
docker run  -v /docker/redis-data:/backup ubuntu ls /backup

共享卷

使用*-volumes-from* 可以把源容器的映射的卷映射到目标容器上。

下面的例子,可以把redis容器的卷映射给Ubuntu容器。*/data仅在Redis容器上存在,但是因为-volumes-from*语句,Ubuntu容器也可以访问到数据。

1
docker run --volumes-from r1 -it ubuntu ls /data

这样,就可以访问其他容器的卷,而不必关心这个容器是如何跟主机持久化数据的。

只读卷

挂在卷会给容器对目录的全部的读取和写入权限。不过可以使用*:ro*命令来限制为只读权限。

如果容器试图修改数据会发生错误。

1
docker run -v /docker/redis-data:/data:ro -it ubuntu rm -rf /data

创建network

首先要使用cli创建一个network,它可以连接上多个容器,使容器可以彼此相互发现。

这个例子中,我们以创建一个backend-network开始,所有连接到后端的容器都在这个网络上。

1
docker network create backend-network

使用*-net*属性连接到网络

1
docker run -d --name=redis --net=backend-network redis

Network通信

与links的通信方式不同,docker的network的行为类似于传统的网络连接-节点可以连接或者卸下连接。

首先你会发现docker不再给容器创建环境变量,不再更新hosts文件。用下面的两个语句可以验证。

1
docker run --net=backend-network alpine env
1
docker run --net=backend-network alpine cat /etc/hosts

取而代之的是,容器间通信会通过docker内嵌的DNS服务器。这个dns服务器会被分配到各个容器,IP是127.0.0.11,配置到/etc/resolv.conf文件中。

1
docker run --net=backend-network alpine cat /etc/resolv.conf

当容器试图使用通用的名字(例如:Redis)去连接其他容器时,DNS服务器会返回对应容器的IP地址。这个例子里,Redis的全名是redis.backend-network

1
docker run --net=backend-network alpine ping -c1 redis

连接两个容器

docker支持容器同时连接多个网络。

举个例子,让我们再创建一个带有Nodejs的网络,然后与已经建立好的Redis实例通信。

首先用相同的方式建立网络

1
docker network create frontend-network

然后使用connect命令,可以把已经存在的实例连接到网络上。

1
docker network connect frontend-network redis

当我们启动这个web服务器,并且连接到网络的时候,它就可以与Redis实例通信了。

1
docker run -d -p 3000:3000 --net=frontend-network katacoda/redis-node-docker-example

创建别名

在网络模式下Links方式仍然被支持,并提供了一种方式给容器定义别名。这样会给容器一个额外的Dns入口名字和被发现的方式。When using –link the embedded DNS will guarantee that localised lookup result only on that container where the –link is used.

另一种方式是连接到网络的时候设置别名。

下面的例子就是把Redis实例连接到网络时使用别名db。

1
2
docker network create frontend-network2
docker network connect --alias db frontend-network2 redis

当容器试图使用db这个名字请求服务时,会被提供Redis容器的IP。

1
docker run --net=frontend-network2 alpine ping -c1 db

容器断线

网络建立好之后,可以使用CLI来查询详细信息。

下面的语句可以列出宿主机上所有的网络。

1
docker network ls

可以查询网络详细,来看有哪些容器连接在这个网络上,并查看IP。

1
docker network inspect frontend-network

下面的语句可以把redis容器从网络frontend-network中断开。

1
docker network disconnect frontend-network redis

启动redis

容器间连接的大多数场景都是应用服务连接数据仓库。创建连接时的关键是容器名字。给被连接的容器起个友好的名字会让连接变得简单。

运行一个redis,命名成:redis-server。这个redis容器就是我们的数据源容器

1
docker run -d --name redis-server redis

创建连接

启动一个容器并连接一个数据源容器需要使用的语句是:*-link <container-name|id>:*

别名用来配置应用程序容器是如何调用数据源的配置信息的,当更改到其他环境的时候,就不需要再修改配置信息了。

连接如何工作

这个例子中,我们使用Alpine容器连接到redis-server(别名命名成了redis)。

连接被创建时,docker会做两件事。

一,docker会基于连接,向容器中创建一些环境变量。根据这些环境变量可以根据给定的名字获取到一些信息,比如端口号,ip地址。

通过env命令可以输出所有的环境变量。

1
docker run --link redis-server:redis alpine env

二,docker会将容器的Host文件更新3个连接到数据源容器的名字,源名字,别名和hash-id。可以使用cat /etc/hosts来查看。

1
docker run --link redis-server:redis alpine cat /etc/hosts

例子

连接建立之后,可以ping数据源容器。

1
docker run --link redis-server:redis alpine ping -c 1 redis

连接到应用

连接创建之后,应用容器就可以连接到redis了。

1
docker run -d -p 3000:3000 --link redis-server:redis katacoda/redis-node-docker-example

连接到redis-cli

使用下面的命令可以启动一个redis-cli容器,并通过别名连接到redis服务容器。

1
docker run -it --link redis-server:redis redis redis-cli -h redis

使用redis的命令查看redis(比如:KEYS *),quit命令用于退出cli。