Docker学习(5)构建多容器的应用栈nodejs+redis

来源:互联网 发布:linux中创建文件命令 编辑:程序博客网 时间:2024/06/01 08:41

通过《第一本Docker书》,上次练习到构建Apache+Jekyll服务和Java应用,继续啃~

继续学习构建多容器的应用栈nodejs+redis。我们会构建一系列的镜像来支持部署多容器的应用。
1.一个Node容器,用来服务于Node应用,这个容器会链接到。
2.一个Redis主容器,用于保存和集群化应用状态,这个容器会链接到。
3.两个Redis副本容器,用于集群化应用状态。
4.一个日志容器,用于捕获应用日志。
我们的Node应用程序会运行在一个容器中,它后面会有一个配置为“主-副本”模式运行在多个容器中的Redsi集群。


一、创建Node.js镜像

1.mkdir -p nodejs && cd nodejs

2.mkdir -p nodeapp && cd nodeapp

3.wget https://raw.githubusercontent.com/jamtur01/dockerbook-code/master/code/6/node/nodejs/nodeapp/package.json

4.wget https://raw.githubusercontent.com/jamtur01/dockerbook-code/master/code/6/node/nodejs/nodeapp/server.js

注:download到nodejs/nodeapp/下


5.cd .. 返回到nodejs目录下

6.vim Dockerfile

#nodejs构建FROM ubuntu:14.04MAINTAINER James Turnbull ENV REFRESHED_AT 2016-06-01RUN apt-get -qq updateRUN apt-get -qq install nodejs npmRUN ln -s /usr/bin/nodejs /usr/bin/nodeRUN mkdir -p /var/log/nodeappADD nodeapp /opt/nodeapp/WORKDIR /opt/nodeappRUN npm installVOLUME [ "/var/log/nodeapp" ]EXPOSE 3000ENTRYPOINT [ "nodejs", "server.js" ]
注:我们将nodeapp的源代码通过ADD指令添加到/opt/nodeapp目录。这个Node.js应用是一个简单的Express服务器,包括一个存放应用依赖信息的package.json文件和包含实际应用代码的server.js文件。


7.构建nodejs:docker build -t smart/nodejs .


二、创建Redis基础镜像

1.mkdir redis_base && cd redis_base

2.vim Dockerfile

#构建redis基础FROM ubuntu:14.04MAINTAINER James Turnbull ENV REFRESHED_AT 2017-06-01RUN apt-get -qq updateRUN apt-get install -qq software-properties-common python-software-propertiesRUN add-apt-repository ppa:chris-lea/redis-serverRUN apt-get -qq updateRUN apt-get -qq install redis-server redis-toolsVOLUME [ "/var/lib/redis", "/var/log/redis" ]EXPOSE 6379CMD []
注:这个Redis基础镜像安装了最新版本的Redis(从PPA库安装,而不是使用Ubuntu自带的较老的Redis包),指定了两个VOLUME(/var/lib/redis和/var/log/redis),公开了Redis的默认端口6379。因为不会执行这个镜像,所以没有包含ENTRYPOINT或者CMD指令。


3.构建redis:docker build -t smart/redis .


三、创建Redis主镜像

1.mkdir redis_primary && cd redis_primary

2.vim Dockerfile

#redis主镜像FROM smart/redisMAINTAINER James Turnbull ENV REFRESHED_AT 2016-06-01ENTRYPOINT [ "redis-server", "--protected-mode no", "--logfile /var/log/redis/redis-server.log" ]


注:Redis主镜像基于之前的smart/redis镜像,并通过ENTRYPOINT指令指定了Redis服务启动命令,Redis服务的日志文件保存到/var/log/redis/redis-server.log。

3.构建:docker build -t smart/redis_primary .


四、创建Redis副本镜像

1.mkdir redis_replica && cd redis_replica

2.vim Dockerfile

#构建redis副本镜像FROM smart/redisMAINTAINER James Turnbull ENV REFRESHED_AT 2016-06-01ENTRYPOINT [ "redis-server", "--protected-mode no", "--logfile /var/log/redis/redis-replica.log", "--slaveof redis_primary 6379" ]
注:Redis副本镜像也是基于jamtur01/redis构建的,并且通过ENTRYPOINT指令指定了运行Redis服务器的命令,设置了日志文件和slaveof选项。这就把Redis配置为主-副本模式,从这个镜像构建的任何容器都会将redis_primary主机的Redis作为主服务,连接其6379端口,成为其对应的副本服务器。


3.构建:docker build -t smart/repllica .


整体目录结构:



五、创建Redis后端集群

1.创建集群所需要的网络express,docker network create express


2.创建redis主容器

docker run -d -h redis_primary --net express --name redis_primary smart/redis_primary

注:这里使用docker run命令从jamtur01/redis_primary镜像创建了一个容器。这里使用了一个以前没有见过的新标志-h,这个标志用来设置容器的主机名。这会覆盖默认的行为(默认将容器的主机名设置为容器ID)并允许我们指定自己的主机名。使用这个标志可以确保容器使用redis_primary作为主机名,并被本地的DNS服务正确解析。
我们已经指定了--``name标志,确保容器的名字是redis_primary,我们还指定了--``net标志,确保``该容器``在express网络中运行。稍后我们会看到,我们将使用这个网络来保证容器连通性。


4.日志:docker logs redis_primary,发现不会有日志出来

5.docker run -ti --rm --volumes-from redis_primary ubuntu cat /var/log/redis/redis-server.log 会有日志


6.创建Redis副本容器1:

docker run -d -h redis_replica1 --name redis_replica1 --net express smart/redis_replica

7.查看新容器1日志:

docker run -ti --rm --volumes-from redis_replica1 ubuntu cat /var/log/redis/redis-replica.log


8.创建Redis副本容器2:

docker run -d -h redis_replica2 --name redis_replica2 --net express smart/redis_replica

9.查看新容器2日志:

docker run -ti --rm --volumes-from redis_replica2 ubuntu cat /var/log/redis/redis-replica.log


六、创建Node容器

1.docker run -d --name nodeapp -p 3000:3000 --net express smart/nodejs

2.查看日志:docker logs nodeapp



七、捕获应用日志Logstash

1.mkdir logstash && cd logstash

2.vim Dockerfile

#构建logstashFROM ubuntu:14.04MAINTAINER James Turnbull ENV REFRESHED_AT 2016-06-01RUN apt-get -qq updateRUN apt-get -qq install wgetRUN wget -O - http://packages.elasticsearch.org/GPG-KEY-elasticsearch |  apt-key add -RUN echo 'deb http://packages.elasticsearch.org/logstash/1.5/debian stable main' > /etc/apt/sources.list.d/logstash.listRUN apt-get -qq updateRUN apt-get -qq install logstash default-jdkADD logstash.conf /etc/WORKDIR /opt/logstashENTRYPOINT [ "bin/logstash" ]CMD [ "--config=/etc/logstash.conf" ]
3.vim logstash.conf

#logstash.conf文件input {  file {    type => "syslog"    path => ["/var/log/nodeapp/nodeapp.log", "/var/log/redis/redis-server.log"]  }}output {  stdout {    codec => rubydebug  }}
注:这个Logstash配置很简单,它监控两个文件,
即/var/log/nodeapp/nodeapp.log和/var/log/redis/redisserver.log。Logstash会一直监视这两个文件,将其中新的内容发送给Logstash。配置文件的第二部分是output部分,接受所有Logstash输入的内容并将其输出到标准输出上。


4.构建:docker build -t smart/logstash .

5.创建容器:docker run -d --name logstash --volumes-from redis_primary --volumes-from nodeapp smart/logstash

注:我们成功地启动了一个名为logstash的新容器,并指定了两次--volumes-from标志,分别挂载了redis_primary和nodeapp容器的卷,这样就可以访问Redis和Node的日志文件了。任何加到这些日志文件里的内容都会反映在logstash容器的卷里,并传给Logstash做后续处理。


6.查看日志:docker logs -f logstas

可以刷新网页后看日志,日志信息如图:


至此,构建nodejs+redis多容器应用已经完成了。docker images && docker ps -a



八、不使用SSH管理Docker容器

传统上,使用SSH登入运行环境或者虚拟机管理服务。在Docker里,大部分容器只运行一个进程,所以不能使用这种方法。可是使用卷或者链接完成大部分管理操作。如需要给容器发送信号,可以使用docker kill命令:

docker kill -s <signal> <container>

这个操作会发送指定的信号给容器,而不是杀掉容器。

然而,有时候确实需要登入容器。即便如此,也不需要在容器里执行SSH服务或者打开任何不必要的访问。需要登入容器时,可以使用一个叫nsenter的小工具。

(nsenter一般适用于Docker 1.2 或者更早的版本。docker exec命令是在Docker 1.3中引入的,替换了它的大部分功能。)


工具nsenter可以进入Docker用来构成容器的内核命名空间。它可以进入一个已经存在的命名空间,或者在新的一组命名空间里执行一个进程。

可以通过Docker容器安装nsenter:docker run -v /usr/local/bin:/target smart/nsenter这会把nsenter安装到/usr/local/bin目录下。

(工具nsenter也可能由所使用的Linux发行版(在util-linux包里)提供)


为了使用nsenter,首先要知道要进入的容器的进程ID,可以使用docker inspect命令获得进程PID:

PID=$(docker inspect --format {{.State.Pid}} <container>)


这会在容器里启动一个shell,而不需要SSH或者其他类似的守护进程或者进程:

nsenter --target $PID --mount --uts --ipc --net --pid


我们还可以将想在容器内执行的命令添加在nsenter命令行的后面,如:
nsenter --target $PID --mount --uts --ipc --net --pid ls

这会在目标容器内执行ls命令



新手一枚,欢迎拍砖~ ~ ~


原创粉丝点击