今天尝试了一下使用类slack的网页聊天服务:rocket chat.感觉搭建起来还是挺方便的.当然其中也遇到一些坑,所以把最后成功的方式记录下来.
由于rocket chat使用了mongo做存储,所以也需要启动一个mongo的容器.
今天尝试了一下使用类slack的网页聊天服务:rocket chat.感觉搭建起来还是挺方便的.当然其中也遇到一些坑,所以把最后成功的方式记录下来.
由于rocket chat使用了mongo做存储,所以也需要启动一个mongo的容器.
当容器以docker run方式运行时,可以给容器添加标签。一个容器在任何一个时刻可以有多个标签。
注意这个例子,我们是在CLI里使用标签,而不是使用自动化工具,所以标签并没有使用DNS标记格式。
添加单标签需要使用选项l =
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 |
镜像的标签和容器的标签的作用相同,不过镜像的标签是写在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 |
这些标签会一直存在,即便在镜像被撤掉标签后,撤掉标签后这个信息会是*
查看容器或者镜像的容器可以提供很多有用的信息,但是在生产环境中上千个容器中,使用标签来限定返回的个数会很有用。
使用 docker ps 可以根据lable来过滤指定容器。下面的例子就是过滤lable是user,值是katacoda的容器。
1 | docker ps --filter "label=user=scrapbook" |
使用同样的方式过滤镜像。
1 | docker images --filter "label=vendor=Katacoda" |
过滤时使用的key和value都是大小写敏感的。
标签也可以应用于Docker的daemon上。当启动一个daemon实例时,可以指定标签,例如在开发服务器或者生产服务器上,指定daemon的角色会是不错的选择。
再之后我们会探讨更多的关于Docker配置和标签使用的更多内容。这里我们简单看一下格式:
1 | docker -d \ |
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会记录进程的标准输出和标准错误,并且使用Docker客户端可以访问。
假设后台有一个Redis实例容器在运行,容器名是redis-server。使用Docker客户端,可以使用如下语句来访问标准输出和标准错误。
1 | docker logs redis-server |
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 | docker inspect --format '{{ .HostConfig.LogConfig }}' redis-server |
宿主机的*/docker/redis-data*目录映射到容器的 /data目录
1 | docker run -v /docker/redis-data:/data \ |
使用下面的语句可以向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 |
首先要使用cli创建一个network,它可以连接上多个容器,使容器可以彼此相互发现。
这个例子中,我们以创建一个backend-network开始,所有连接到后端的容器都在这个网络上。
1 | docker network create backend-network |
使用*-net*属性连接到网络
1 | docker run -d --name=redis --net=backend-network redis |
与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 | docker network create frontend-network2 |
当容器试图使用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-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服务容器。
1 | docker run -it --link redis-server:redis redis redis-cli -h redis |
使用redis的命令查看redis(比如:KEYS *),quit命令用于退出cli。