diff --git a/images/container_connect_topology.png b/images/container_connect_topology.png new file mode 100644 index 0000000..5419d56 Binary files /dev/null and b/images/container_connect_topology.png differ diff --git a/images/enterprise_usage.png b/images/enterprise_usage.png new file mode 100644 index 0000000..5682892 Binary files /dev/null and b/images/enterprise_usage.png differ diff --git a/practice/README.md b/practice/README.md index e69de29..692771c 100644 --- a/practice/README.md +++ b/practice/README.md @@ -0,0 +1 @@ +#实战案例 \ No newline at end of file diff --git a/practice/container_connect.md b/practice/container_connect.md index e69de29..0388d67 100644 --- a/practice/container_connect.md +++ b/practice/container_connect.md @@ -0,0 +1,77 @@ +##多台物理主机之间的容器互联(暴露容器到真实网络中) +docker 默认的桥接网卡是docker0。它只会在本机桥接所有的容器网卡,举例来说容器的虚拟网卡在主机上看一般叫做veth*** 而docker只是把所有这些网卡桥接在一起,如下: +``` +[root@opnvz ~]# brctl show +bridge name bridge id STP enabled interfaces +docker0 8000.56847afe9799 no veth0889 + veth3c7b + veth4061 +``` +在容器中看到的地址一般是像下面这样的地址: +``` +root@ac6474aeb31d:~# ip a +1: lo: mtu 1500 qdisc noqueue state UNKNOWN group default + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + inet6 ::1/128 scope host + valid_lft forever preferred_lft forever +11: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 4a:7d:68:da:09:cf brd ff:ff:ff:ff:ff:ff + inet 172.17.0.3/16 scope global eth0 + valid_lft forever preferred_lft forever + inet6 fe80::487d:68ff:feda:9cf/64 scope link + valid_lft forever preferred_lft forever +``` +这样就可以把这个网络看成是一个私有的网络,通过nat 连接外网,如果要让外网连接到容器中,就需要做端口映射,即-p参数(更多原理参见本文第六小节) +如果在企业内部应用,或则做多个物理主机的集群,可能需要将多个物理主机的容器组到一个物理网络中来,那么就需要将这个网桥桥接到我们指定的网卡上。 + +###拓扑图 +主机A和主机B的网卡一都连着物理交换机的同一个vlan 101,这样网桥一和网桥三就相当于在同一个物理网络中了,而容器一、容器三、容器四也在同一物理网络中了,他们之间可以相互通信,而且可以跟同一vlan中的其他物理机器互联。 +![物理拓扑图](../images/container_connect_topology.png) + +###ubuntu示例 +下面以ubuntu为例创建多个主机的容器联网: +创建自己的网桥,编辑/etc/network/interface文件 +``` +auto br0 +iface br0 inet static +address 192.168.7.31 +netmask 255.255.240.0 +gateway 192.168.7.254 +bridge_ports em1 +bridge_stp off +dns-nameservers 8.8.8.8 192.168.6.1 +``` +将docker的默认网桥绑定到这个新建的br0上面,这样就将这台机器上容器绑定到em1这个网卡所对应的物理网络上了。 + +ubuntu修改/etc/default/docker文件 添加最后一行内容 + +``` +# Docker Upstart and SysVinit configuration file +# Customize location of Docker binary (especially for development testing). +#DOCKER="/usr/local/bin/docker" +# Use DOCKER_OPTS to modify the daemon startup options. +#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4" + +# If you need Docker to use an HTTP proxy, it can also be specified here. +#export http_proxy="http://127.0.0.1:3128/" + +# This is also a handy place to tweak where Docker's temporary files go. +#export TMPDIR="/mnt/bigdrive/docker-tmp" + +DOCKER_OPTS="-b=br0" +``` + +在启动docker的时候 使用-b参数 将容器绑定到物理网络上。重启docker服务后,再进入容器可以看到它已经绑定到你的物理网络上了。 + +``` +root@ubuntudocker:~# docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +58b043aa05eb desk_hz:v1 "/startup.sh" 5 days ago Up 2 seconds 5900/tcp, 6080/tcp, 22/tcp yanlx +root@ubuntudocker:~# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.7e6e617c8d53 no em1 + vethe6e5 +``` +这样就直接把容器暴露到你的物理网络上了,多台物理主机的容器也可以相互联网了。需要注意的是,这样就需要自己来保证容器的网络安全了。 \ No newline at end of file diff --git a/practice/environment.md b/practice/environment.md index e69de29..96fd86e 100644 --- a/practice/environment.md +++ b/practice/environment.md @@ -0,0 +1,10 @@ +#中小企业docker环境搭建 +docker对于中小企业来说,搭建paas没有那个精力,也没那个必要,用做个人的sandbox用处又小了点,个人认为作为中小企业可以用docker来标准化开发、测试、生产环境。 + + +![企业应用结构](../images/enterprise_usage.png) + + +docker占用资源小,在一台E5 128G内存的服务器服务器上部署100个容器都绰绰有余,可以单独抽一个容器或则直接在宿主物理主机上部署samba,利用samba的home分享方案将每个用户的home目录映射到开发中心和测试部门的windows机器上。可以针对项目组,由架构师搭建好一个标准的容器环境供项目组和测试部门使用,每个开发工程师可以拥有自己单独的容器,通过docker run -v 将用户的home目录映射到容器中。需要提交测试时,只需要将代码移交给测试部门,然后分配一个容器使用-v 加载测试部门的home目录启动即可。这样,在公司内部的开发、测试基本就统一了,不会出现开发提交的代码,测试 部门部署不了的问题。 + +测试发布测试通过的报告后,架构师再一次检测容器环境,就可以直接交由部署工程师将代码和容器分别部署到生产环境中了。这种方式的部署横向性能的扩展性也极好。 diff --git a/practice/local_repo.md b/practice/local_repo.md index e69de29..fd554db 100644 --- a/practice/local_repo.md +++ b/practice/local_repo.md @@ -0,0 +1,107 @@ +##部署本地仓库 +由于网络的关系,国内用户在使用docker hub的时候,很难pull一个基本的镜像下来。 +本节介绍如何创建部署本地仓库。 + +###安装docker +参见本文第三小节 +###从文件系统创建一个image镜像 +创建镜像有很多方法,官方的推荐是pull一个,不过在墙内,想pull一个基本的ubuntu都没办法完成。 +这里推荐一个办法就是从一个文件系统import一个镜像,个人推荐可以使用opvz的模板来创建:(openvz可以说是容器虚拟化的先锋吧) +openvz的模板下载地址如下: +http://openvz.org/Download/templates/precreated +下载完之后,比如:下载了一个ubuntu14.04的镜像 +使用以下命令: +``` +sudo cat ubuntu-14.04-x86_64-minimal.tar.gz |docker import - ubuntu:14.04 +``` +然后用docker images看下: +``` +docker images +REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +ubuntu 14.04 05ac7c0b9383 17 seconds ago 215.5 MB +``` +就多了一个我们的ubuntu镜像 + +###创建私有仓库 +官方指南称最简单的办法是 docker run -p 5000:5000 registry,如果被墙了,也无法下载该images。感谢CSDN,我有一个1M的腾讯云服务器,上面搭建了一个私有仓库大家可以使用 +docker pull 203.195.193.251:5000/registry +到我的服务器下载 速度虽然慢点,但有保证! +另外的方法是使用刚才的创建的ubuntu来创建,官方有个docker仓库的源码地址 https://github.com/dotcloud/docker-registry 下载私有仓库的源码,可以根据上面的docker file来创建。 + +也可以参考: +http://www.vpsee.com/2013/11/build-your-own-docker-private-regsitry-service/ + +###在私有仓库上传、下载、搜索images +创建好自己的私有仓库之后,可以使用docker tag 一个镜像,然后push,然后在别的机器上pull下来就好了。这样我们的局域网私有docker仓库就搭建好了。 +步骤如下: +使用 docker run -p 5000:5000 registry 在局域网的一台机器上开启一个容器之后,我的局域网私有仓库地址为192.168.7.26:5000 +先在本机看下现有的images +``` +root ~ # docker images +REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB +ubuntu 14.04 ba5877dc9bec 6 weeks ago 192.7 MB +使用 docker tag 将ba58这个image标记为192.168.7.26:5000/test +root ~ # docker tag ba58 -t 192.168.7.26:5000/test +root ~ # docker images +REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +ubuntu 14.04 ba5877dc9bec 6 weeks ago 192.7 MB +ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB +192.168.7.26:5000/test latest ba5877dc9bec 6 weeks ago 192.7 MB +``` +使用docker push 上传我们标记的新image,这里因为我的服务器上已经有这个images,所有在上传文件层的时候,都跳过了,但是标记还是不一样的。 +``` +root ~ # docker push 192.168.7.26:5000/test +The push refers to a repository [192.168.7.26:5000/test] (len: 1) +Sending image list +Pushing repository 192.168.7.26:5000/test (1 tags) +Image 511136ea3c5a already pushed, skipping +Image 9bad880da3d2 already pushed, skipping +Image 25f11f5fb0cb already pushed, skipping +Image ebc34468f71d already pushed, skipping +Image 2318d26665ef already pushed, skipping +Image ba5877dc9bec already pushed, skipping +Pushing tag for rev [ba5877dc9bec] on {http://192.168.7.26:5000/v1/repositories/test/tags/latest} +root ~ # curl http://192.168.7.26:5000/v1/search +The program 'curl' is currently not installed. You can install it by typing: +apt-get install curl +``` +现在的私有仓库只支持这样简陋的搜索方式,如果没有安装curl,可以先安装后再使用 +``` +root ~ # apt-get install curl +Reading package lists... Done +Building dependency tree +Reading state information... Done +The following NEW packages will be installed: + curl +0 upgraded, 1 newly installed, 0 to remove and 570 not upgraded. +Need to get 123 kB of archives. +After this operation, 313 kB of additional disk space will be used. +Get:1 http://192.168.7.26/ubuntu/ trusty/main curl amd64 7.35.0-1ubuntu2 [123 kB] +Fetched 123 kB in 0s (7457 kB/s) +Selecting previously unselected package curl. +(Reading database ... 184912 files and directories currently installed.) +Preparing to unpack .../curl_7.35.0-1ubuntu2_amd64.deb ... +Unpacking curl (7.35.0-1ubuntu2) ... +Processing triggers for man-db (2.6.7.1-1) ... +Setting up curl (7.35.0-1ubuntu2) ... +root ~ # curl http://192.168.7.26:5000/v1/search +{"num_results": 7, "query": "", "results": [{"description": "", "name": "library/miaxis_j2ee"}, {"description": "", "name": "library/tomcat"}, {"description": "", "name": "library/ubuntu"}, {"description": "", "name": "library/ubuntu_office"}, {"description": "", "name": "library/desktop_ubu"}, {"description": "", "name": "dockerfile/ubuntu"}, {"description": "", "name": "library/test"}]} +``` +这里我们可以看到 {"description": "", "name": "library/test"} 表示我们的image已经被成功上传了。 +现在我们到另外一台机器上下载这个images +``` +[root@opnvz ~]# docker pull 192.168.7.26:5000/test +Pulling repository 192.168.7.26:5000/test +ba5877dc9bec: Download complete +511136ea3c5a: Download complete +9bad880da3d2: Download complete +25f11f5fb0cb: Download complete +ebc34468f71d: Download complete +2318d26665ef: Download complete +[root@opnvz ~]# docker images +REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +192.168.7.26:5000/test latest ba5877dc9bec 6 weeks ago 192.7 MB +``` + +这样我们就可以在新的机器上使用这个images了! \ No newline at end of file diff --git a/practice/supervisor.md b/practice/supervisor.md index e69de29..1bf2f8e 100644 --- a/practice/supervisor.md +++ b/practice/supervisor.md @@ -0,0 +1,54 @@ +##在Docker中使用 Supervisor来管理进程 +docker 容器在启动的时候开启单个进程,比如,一个ssh或则apache 的daemon服务。但我们经常需要在一个机器上开启多个服务,这可以有很多方法,最简单的就是把多个启动命令方到一个启动脚本里面,启动的时候直接启动这个脚本,另外就是安装进程管理工具。. +本小节将使用进程管理工具supervisor来管理容器中的多个进程。使用Supervisor可以更好的控制、管理、重启我们希望运行的进程。在这里我们演示一下如何同时使用ssh和apache服务。 +###dockerfile +FROM ubuntu:13.04 +MAINTAINER examples@docker.com +RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list +RUN apt-get update +RUN apt-get upgrade -y + +安装supervisor +安装 ssh apache supervisor + +RUN apt-get install -y openssh-server apache2 supervisor +RUN mkdir -p /var/run/sshd +RUN mkdir -p /var/log/supervisor +这里安装3个软件,还创建了2个用来允许ssh和supervisor的目录 +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +添加supervisor‘s的配置文件 +添加配置文件到对应目录下面 +映射端口,开启supervisor +使用dockerfile来映射指定的端口,使用cmd来启动supervisord +EXPOSE 22 80 +CMD ["/usr/bin/supervisord"] +这里我们映射了22 和80端口,使用supervisord的可执行路径启动服务。 +###supervisor配置文件内容 +``` +[supervisord] +nodaemon=true +[program:sshd] +command=/usr/sbin/sshd -D + +[program:apache2] +command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" +``` +配置文件包含目录和进程,第一段supervsord配置软件本身,使用nodaemon参数来运行。下面2段包含我们要控制的2个服务。每一段包含一个服务的目录和启动这个服务的命令 +###使用方法 +创建image +``` +$ sudo docker build -t test/supervisord . +``` +启动我们的supervisor容器 +``` +$ sudo docker run -p 22 -p 80 -t -i test/supervisords +2013-11-25 18:53:22,312 CRIT Supervisor running as root (no user in config file) +2013-11-25 18:53:22,312 WARN Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing +2013-11-25 18:53:22,342 INFO supervisord started with pid 1 +2013-11-25 18:53:23,346 INFO spawned: 'sshd' with pid 6 +2013-11-25 18:53:23,349 INFO spawned: 'apache2' with pid 7 +``` +使用docker run来启动我们创建的容器。使用多个-p 来映射多个端口,这样我们就能同时访问ssh和apache服务了。 + +###可以使用这个方法创建一个只有ssh服务基础image +之后创建image可以以这个image为基础来创建 \ No newline at end of file diff --git a/practice/tomcat.md b/practice/tomcat.md index e69de29..13ccb67 100644 --- a/practice/tomcat.md +++ b/practice/tomcat.md @@ -0,0 +1,74 @@ +##创建tomcat/weblogic集群 +###安装tomcat镜像 +准备好需要的jdk tomcat等软件放到home目录下面,启动一个虚拟机 +``` +docker run -t -i -v /home:/opt/data --name mk_tomcat ubuntu /bin/bash +``` +这条命令挂载本地home目录到虚拟机的/opt/data目录,虚拟机内目录若不存在,则会自动创建。接下来就是tomcat的基本配置,jdk环境变量设置好之后,将tomcat程序放到/opt/apache-tomcat下面 +编辑/etc/supervisor/conf.d/supervisor.conf文件,添加tomcat项 +``` +[supervisord] +nodaemon=true + +[program:tomcat] +command=/opt/apache-tomcat/bin/startup.sh + +[program:sshd] +command=/usr/sbin/sshd -D +docker commit ac6474aeb31d tomcat +``` + +新建tomcat文件夹,新建Dockerfile +``` +FROM tomcat +EXPOSE 22 8080 +CMD ["/usr/bin/supervisord"] +``` +根据dockerfile 创建image +``` +docker build tomcat tomcat +``` +###安装weblogic镜像 + +步骤和tomcat基本一致,这里贴一下配置文件 +``` +supervisor.conf +[supervisord] +nodaemon=true + + +[program:weblogic] +command=/opt/Middleware/user_projects/domains/base_domain/bin/startWebLogic.sh + +[program:sshd] +command=/usr/sbin/sshd -D +dockerfile +FROM weblogic +EXPOSE 22 7001 +CMD ["/usr/bin/supervisord"] +``` + +###tomcat/weblogic 镜像的使用 +1)存储的使用 +在启用docker run 的时候,使用 -v参数 +-v, --volume=[] Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container) +将本地磁盘映射到虚拟机内部,它在主机和虚拟机容器之间是实时变化的,所以我们更新程序、上传代码只需要更新物理主机的目录就可以了,数据存储的详细介绍请参见本文第七小节 +2)tomcat和weblogic集群的实现 +tomcat只要开启多个容器即可 +docker run -d -v -p 204:22 -p 7003:8080 -v /home/data:/opt/data --name tm1 tomcat /usr/bin/supervisord +docker run -d -v -p 205:22 -p 7004:8080 -v /home/data:/opt/data --name tm2 tomcat /usr/bin/supervisord +docker run -d -v -p 206:22 -p 7005:8080 -v /home/data:/opt/data --name tm3 tomcat /usr/bin/supervisord + + +这里说一下weblogic的配置,大家知道weblogic有一个域的概念。如果要使用常规的administrator +node的方式部署,就需要在supervisord中分别写出administartor server和node server的启动脚本,这样做的优点是: +* 可以使用weblogic的集群,同步等概念 +* 部署一个集群应用程序,只需要安装一次应用到集群上即可 +缺点是: +* docker配置复杂了 +* 没办法自动扩展集群的计算容量,如需添加节点,需要在administrator上先创建节点,然后再配置心的容器supervisor启动脚本,然后再启动容器 +另外种方法是将所有的程序都安装在adminiserver上面,需要扩展的时候,启动多个节点即可,它的优点和缺点和上一中方法恰恰相反。(目前我使用这种方式来部署开发和测试环境) +docker run -d -v -p 204:22 -p 7001:7001 -v /home/data:/opt/data --name node1 weblogic /usr/bin/supervisord +docker run -d -v -p 205:22 -p 7002:7001 -v /home/data:/opt/data --name node2 weblogic /usr/bin/supervisord +docker run -d -v -p 206:22 -p 7003:7001 -v /home/data:/opt/data --name node3 weblogic /usr/bin/supervisord + +这样在前端使用nginx 来做负载均衡就可以完成配置了