Docker容器學習梳理 - 應用程式容器環境部署

散盡浮華發表於2017-02-21

 

關於國內Docker映象,可以參考:Docker容器學習梳理--基礎知識(2) 的Docker映象使用。

如果我們需要在Docker環境下部署tomcat、redis、mysql、nginx、php等應用服務環境,有下面三種方法:

1)根據系統映象建立Docker容器,這時容器就相當於是一個虛擬機器,進入容器內部署應用環境。
   然後將這種應用容器提交為新的映象,最後基於這種新的應用映象建立容器,建立時做好埠對映,就可以在外部訪問這些應用了。
2)直接通過docker pull拉取別人提交好的tomcat、nginx等應用程式映象,然後基於這些映象去建立容器。
3)通過dockerfile製作自己的應用程式映象。

根據系統映象部署應用容器,簡單做法如下:
1)啟動centos系統映象的容器my_container
2)在my_container容器裡部署例如nginx、php、mysql、php的服務
3)將部署完對應服務的容器my_container提交為新的映象
4)然後根據新映象去建立容器
5)這個新映象可以打包,匯入到別的Docker伺服器上使用

啟動容器時,記得要做好埠對映和目錄對映。埠對映是為了實現在外部能成功訪問到容器裡的應用服務。目錄對映是為了實現宿主機和容器的資料共享,這樣要對容器做修改時,直接在宿主機的對映目錄下做修改就行。修改資料的操作最好不要在容器內進行原則上來說一個應用啟動一個容器,最好別在一個容器內啟動多個應用。

下面列舉幾個通過應用服務映象部署環境的例子:
Docker宿主機內網ip:192.168.1.23
Docker宿主機外網ip:103.110.186.23
Docker部分命令解釋:

-i:表示以“互動模式”執行容器
-t:表示容器啟動後會進入其命令列。加入這兩個引數後,容器建立就能登入進去。即分配一個偽終端。
--name :表示建立的容器名為my-nginx
-v:表示目錄對映關係(前者是宿主機目錄,後者是對映到宿主機上的目錄),可以使用多個-v做多個目錄或檔案對映。
    注意:最好做目錄對映,在宿主機上做修改,然後共享到容器上。
-d:在run後面加上-d引數,則會建立一個守護式容器在後臺執行(這樣建立容器後不會自動登入容器,如果只加-i -t兩個引數,建立後就會自動進去容器)。docker attch登入容器時如果卡著,按ctrl+c。
-p:表示埠對映,前者是宿主機埠,後者是容器內的對映埠。可以使用多個-p做多個埠對映

如果建立容器時報如下錯:

docker: Error response from daemon: failed to create endpoint mosredis on network bridge: iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.6  -j ACCEPT: iptables: No chain/target/match by that name.
 (exit status 1).

解決辦法:
一般來說,重啟docker服務,即可解決這個問題。
[root@localhost ~]# systemctl restart docker
[root@localhost ~]# 
----------------------------------
如果重啟docker服務解決不了,那麼如下操作:
[root@localhost ~]# pkill docker
[root@localhost ~]# iptables -t nat -F
[root@localhost ~]# ifconfig docker0 down
[root@localhost ~]# brctl delbr docker0

一、redis容器環境部署

拉取redis映象(這裡拉取的是官方映象。也可以自己製作redis映象)
[root@localhost ~]# docker pull redis
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              e4a35914679d        2 weeks ago         182.9 MB
 
用下面的命令啟動Redis容器,記得要帶上“-d”引數.在run後面加上-d引數,則會建立一個守護式容器在後臺執行。 
[root@localhost ~]# docker run --name myredis -d docker.io/redis
7a273a550005b8494be9d48970a6cc4efbaddd8a152261310a07237d43c9eb16

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
7a273a550005        docker.io/redis     "docker-entrypoint.sh"   3 seconds ago       Up 2 seconds        6379/tcp            myredis
 
連線容器的redis
1)第一種方式:找出容器的ip
[root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' 7a273a550005
172.17.0.2
 
然後連線容器的redis
[root@localhost ~]# redis-cli -h 172.17.0.2 -p 6379
redis 172.17.0.2:6379> ping      //驗證下redis服務是否已經連線上
PONG
redis 172.17.0.2:6379>

2)第二種方式:
[root@localhost ~]# docker run --name myredis -d docker.io/redis
5e260566925e9d6a31b47a47124feb10f3dcfce131c6aa67647881da7874502b
    
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5e260566925e        docker.io/redis     "docker-entrypoint.sh"   13 minutes ago      Up 13 minutes       6379/tcp            myredis
    
下面的命令表示新建一個容器(命名為myredis2),將redis-cli執行在裡面。然後使用--link將這個容器和之前的redis容器(myredis)連線起來,並將其別名命名為redisdb。
Docker會在redis容器中的/etc/hosts路徑下為"redisdb"建立一個入口,並指向redis容器的IP地址.
這樣在這兩個容器裡就可以使用“redisdb”來作為提供redis容器的機器名,也就可以利用這個別名來連線容器redis。
[root@localhost ~]# docker run --rm -it --name myredis2 --link myredis:redisdb docker.io/redis /bin/bash
root@4d4b25678b84:/data# redis-cli -h redisdb -p 6379
redisdb:6379> ping
PONG
redisdb:6379>
    
-----------------------------------------------------
當然,這樣也可以如上面先查容器ip進行連線
[root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' 5e260566925e
172.17.0.2
[root@localhost ~]# redis-cli -h 172.17.0.2 -p 6379
redis 172.17.0.2:6379>

3)第三種方式:通過埠對映,外部連線redis容器應用的方法
建立Redis容器例項,這裡使用了Docker的埠對映機制,從而就可以使用Host伺服器的IP訪問這些redis例項.
如下建立三個redis容器例項
[root@localhost ~]# docker run -d --name node1 -p 7001:6379 docker.io/redis
e4b8ca12d9e76441efe2074ab1109757a33a45aff71d1a553140d48d88133372
[root@localhost ~]# docker run -d --name node2 -p 7002:6379 docker.io/redis
a8ee6f48f431651a0342fba289604046cd5b142f53a7eb43f655dde397a06a6f
[root@localhost ~]# docker run -d --name node3 -p 7003:6379 docker.io/redis
2b61bf6765a8c254df9dd41d3ece6b12f4dd768976e6e22f327516063fc2e634
[root@localhost ~]#
 
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
2b61bf6765a8        docker.io/redis     "docker-entrypoint.sh"   48 seconds ago       Up 47 seconds       0.0.0.0:7003->6379/tcp   node3
a8ee6f48f431        docker.io/redis     "docker-entrypoint.sh"   55 seconds ago       Up 55 seconds       0.0.0.0:7002->6379/tcp   node2
e4b8ca12d9e7        docker.io/redis     "docker-entrypoint.sh"   About a minute ago   Up About a minute   0.0.0.0:7001->6379/tcp   node1
 
在容器之間建立連線
可以建立應用程式容器,使用--link引數來建立一個連線redis容器,使用別名,將會在redis容器和redis例項容器中建立一個安全的通訊隧道
 
------------node1操作------------
[root@localhost ~]# docker run --link node1:db -i -t docker.io/redis /bin/bash
root@8fd8d9db3cc1:/data#
 
現在可以測試連線,首先要先檢視下web應用程式容器的環境變數,可以用我們的ip和埠來連線redis容器
root@8fd8d9db3cc1:/data# env | grep DB_
DB_PORT_6379_TCP_PORT=6379
DB_NAME=/nauseous_heisenberg/db
DB_PORT=tcp://172.17.0.2:6379
DB_PORT_6379_TCP=tcp://172.17.0.2:6379
DB_ENV_GOSU_VERSION=1.7
DB_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.2.8.tar.gz
DB_ENV_REDIS_VERSION=3.2.8
DB_PORT_6379_TCP_ADDR=172.17.0.2
DB_PORT_6379_TCP_PROTO=tcp
DB_ENV_REDIS_DOWNLOAD_SHA1=6780d1abb66f33a97aad0edbe020403d0a15b67f
 
可以看到上面命令結果中有一個DB為字首的環境變數列表,DB來自指定別名連線對應的應用容器,這裡就可以使用DB_PORT_6379_TCP_ADDR變數連線到Redis容器。
root@8fd8d9db3cc1:/data# redis-cli -h $DB_PORT_6379_TCP_ADDR
172.17.0.2:6379> ping
PONG
172.17.0.2:6379> set node1 redis-node1
OK
172.17.0.2:6379> get node1
"redis-node1"
172.17.0.2:6379>
 
------------node2操作------------
[root@localhost ~]# docker run --link node2:db2 -i -t docker.io/redis /bin/bash
root@8eb2ccc2aff3:/data# env | grep DB2_
DB2_PORT_6379_TCP_PROTO=tcp
DB2_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.2.8.tar.gz
DB2_PORT_6379_TCP_ADDR=172.17.0.3
DB2_ENV_GOSU_VERSION=1.7
DB2_PORT=tcp://172.17.0.3:6379
DB2_PORT_6379_TCP_PORT=6379
DB2_ENV_REDIS_VERSION=3.2.8
DB2_ENV_REDIS_DOWNLOAD_SHA1=6780d1abb66f33a97aad0edbe020403d0a15b67f
DB2_PORT_6379_TCP=tcp://172.17.0.3:6379
DB2_NAME=/furious_kare/db2
 
root@8eb2ccc2aff3:/data# redis-cli -h $DB2_PORT_6379_TCP_ADDR
172.17.0.3:6379> ping
PONG
172.17.0.3:6379> set node2 redis-node2
OK
172.17.0.3:6379> get node2
"redis-node2"
172.17.0.3:6379>
 
------------node3操作------------
[root@localhost ~]# docker run --link node3:db3 -i -t docker.io/redis /bin/bash
root@d60d074ca66b:/data# env|grep DB3_
DB3_PORT_6379_TCP_ADDR=172.17.0.4
DB3_PORT_6379_TCP_PORT=6379
DB3_PORT_6379_TCP_PROTO=tcp
DB3_ENV_REDIS_DOWNLOAD_SHA1=6780d1abb66f33a97aad0edbe020403d0a15b67f
DB3_NAME=/amazing_kalam/db3
DB3_PORT=tcp://172.17.0.4:6379
DB3_ENV_REDIS_VERSION=3.2.8
DB3_ENV_GOSU_VERSION=1.7
DB3_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.2.8.tar.gz
DB3_PORT_6379_TCP=tcp://172.17.0.4:6379
 
root@d60d074ca66b:/data# redis-cli -h $DB3_PORT_6379_TCP_ADDR
172.17.0.4:6379> ping
PONG
172.17.0.4:6379> set node3 redis-node3
OK
172.17.0.4:6379> get node3
"redis-node3"
172.17.0.4:6379>
 
這樣就可以在docker宿主機或其他伺服器上通過宿主機的ip地址以及對映的埠進行連線
[root@localhost ~]# redis-cli -h 192.168.1.23 -p 7001
redis 192.168.1.23:7001> get node1
"redis-node1"
redis 192.168.1.23:7001>
 
[root@localhost ~]# redis-cli -h 192.168.1.23 -p 7002
redis 192.168.1.23:7002> get node2
"redis-node2"
redis 192.168.1.23:7002>
 
[root@localhost ~]# redis-cli -h 192.168.1.23 -p 7003
redis 192.168.1.23:7003> get node3
"redis-node3"
redis 192.168.1.23:7003>

注意一個細節:
建立應用容器的時候,一般會做埠對映,這樣是為了讓外部能夠訪問這些容器裡的應用。可以通過-P或-p引數來指定埠對映

1)當使用-p標記時,可以指定埠對映,即容器埠對映到宿主機的對應埠。可以用多個-p指定多個埠對映關係。如下:
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              e4a35914679d        2 weeks ago         182.9 MB

[root@localhost ~]# docker run --name myredis -p 63799:6379 -d docker.io/redis
f5d5ff51ace01c5f26fcd65a6ca4853f8556a333c812576123ed71fd3d405737

[root@localhost ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
f5d5ff51ace0        docker.io/redis     "docker-entrypoint.sh"   6 seconds ago       Up 5 seconds        0.0.0.0:63799->6379/tcp   myredis

[root@localhost ~]# docker run --rm -it --name myredis2 --link myredis:redisdb docker.io/redis /bin/bash
root@16b660ff9f65:/data# redis-cli -h redisdb -p 6379
redisdb:6379> ping
PONG
redisdb:6379> set test linux
OK
redisdb:6379>

在別的機器上通過訪問本機的63799埠連線這個容器的redis
[root@linux-node2 ~]# redis-cli -h 192.168.1.23 -p 63799
192.168.1.23:63799> get test
"linux"
192.168.1.23:63799> 


2)當使用-P標記時,Docker 會隨機對映一個 49000~49900 的埠到內部容器開放的網路埠。如下:
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              e4a35914679d        2 weeks ago         182.9 MB

[root@localhost ~]# docker run --name myredis -P -d docker.io/redis
805d0e21e531885aad61d3e82395210b50621f1991ec4b7f9a0e25c815cc0272

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
805d0e21e531        docker.io/redis     "docker-entrypoint.sh"   4 seconds ago       Up 3 seconds        0.0.0.0:32768->6379/tcp   myredis

從上面的結果中可以看出,本地主機的32768埠被對映到了redis容器的6379埠上,也就是說訪問本機的32768埠即可訪問容器內redis埠。

測試看下,登陸redis容器,隨意寫個資料
[root@localhost ~]# docker run --rm -it --name myredis2 --link myredis:redisdb docker.io/redis /bin/bash
root@be44d955d6f4:/data# redis-cli -h redisdb -p 6379
redisdb:6379> set wangshibo huanqiu
OK
redisdb:6379> 

在別的機器上通過上面對映的埠32768連線這個容器的redis
[root@linux-node2 ~]# redis-cli -h 192.168.1.23 -p 32768
192.168.1.23:32768> get wangshibo
"huanqiu"

二、nginx容器環境部署(下面是自己製作的應用映象)

[root@linux-node2 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
centos                       latest              67591570dd29        3 months ago        191.8 MB

為了防止centos7映象容器裡出現:Failed to get D-Bus connection: Operation not permitted 這個bug錯誤,需要在啟動容器的時候新增--privileged引數
並且後面登入容器執行的命令是/sbin/init,如下:
[root@linux-node2 ~]# docker run --privileged -t -i centos /sbin/init

上面命令執行後,會一直卡著。這個不要緊,再開啟一個終端視窗,檢視並登入容器:
[root@linux-node2 ~]# docker ps
CONTAINER ID    IMAGE       COMMAND        CREATED          STATUS         PORTS  NAMES
eaf66f1e43ab    centos      "/sbin/init"   16 seconds ago   Up 15 seconds         hungry_khorana

[root@linux-node2 ~]# docker exec -it eaf66f1e43ab /bin/bash
[root@eaf66f1e43ab /]#

接著在容器裡安裝nginx
[root@eaf66f1e43ab /]# yum install -y wget lsof vim

新增CentOS 7 Nginx yum資源庫,然後安裝nginx
[root@eaf66f1e43ab /]# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
[root@eaf66f1e43ab /]# yum install -y nginx

[root@eaf66f1e43ab conf.d]# pwd 
/etc/nginx/conf.d
[root@eaf66f1e43ab conf.d]# cat test.conf 
server {
listen 8080;
server_name localhost;
location / {
root /var/www/html;
index index.html;
}
}

[root@eaf66f1e43ab conf.d]# mkdir -p /var/www/html
[root@eaf66f1e43ab conf.d]# cat /var/www/html/test.html
this is nginx page of docker!!

[root@eaf66f1e43ab conf.d]# systemctl start nginx.service

將這個容器提交為新的映象
[root@linux-node2 ~]# docker stop eaf66f1e43ab
[root@linux-node2 ~]# docker commit eaf66f1e43ab my-nginx
[root@linux-node2 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
my-nginx                     latest              8dacda904e00        45 minutes ago      314.4 MB

將上面提交的映象打包
[root@linux-node2 ~]# docker save my-nginx > /root/my-nginx.tar.gz

然後將這個映象包上傳到別的機器上,比如上傳到192.168.1.23機器上的/root下。
在192.168.1.23機器上匯入新映象
[root@localhost ~]# docker load < /root/my-nginx.tar.gz
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
my-nginx            latest              8dacda904e00        50 minutes ago      314.4 MB

啟動nginx容器
[root@localhost ~]# docker run -t -i --privileged --name nginx -v /var/www/html:/var/www/html -p 8899:8080 my-nginx /sbin/init

上面命令執行後會卡著,在另一個埠視窗:
[root@localhost ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
3b5cbea50052        my-nginx            "/sbin/init"        36 seconds ago      Up 35 seconds       0.0.0.0:8899->8080/tcp   nginx
[root@localhost ~]# docker exec -t -i 3b5cbea50052 /bin/bash 
[root@3b5cbea50052 /]# 

[root@3b5cbea50052 /]# systemctl start nginx.service
[root@3b5cbea50052 /]# ps -ef|grep nginx
root       117     1  0 16:47 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx      118   117  0 16:47 ?        00:00:00 nginx: worker process
root       120    88  0 16:47 ?        00:00:00 grep --color=auto nginx
[root@3b5cbea50052 /]# cat /etc/nginx/conf.d/test.conf 
server {
listen 8080;
server_name localhost;
location / {
root /var/www/html;
index index.html;
}
}

[root@3b5cbea50052 /]# cat /etc/nginx/conf.d/test.conf 
server {
listen 8080;
server_name localhost;
location / {
root /var/www/html;
index index.html;
}
}

[root@localhost ~]# cat /var/www/html/index.html
this is page of Docker-nginx-test!!!

Docker宿主機的iptables防火牆設定好對映埠8899

測試訪問

----------------------------------------------------------------------------
根據nginx應用映象直接建立:

[root@localhost ~]# docker pull nginx
[root@localhost ~]# docker images
docker.io/nginx                latest              5e69fe4b3c31        4 days ago          182.5 MB

[root@localhost ~]# docker run -ti -d --name my-nginx -p 9988:80 docker.io/nginx /bin/bash
55ae1f2b1eca6638e11865171f322a55cfa277a0aec06526428a1887229b022e
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                       COMMAND             CREATED             STATUS              PORTS                           NAMES
55ae1f2b1eca        docker.io/nginx             "/bin/bash"         3 seconds ago       Up 3 seconds        443/tcp, 0.0.0.0:9988->80/tcp   my-nginx

[root@localhost ~]# docker exec -ti my-nginx /bin/bash
root@55ae1f2b1eca:/# find / -name nginx
/etc/default/nginx
/etc/init.d/nginx
/etc/logrotate.d/nginx
/etc/nginx
/usr/lib/x86_64-linux-gnu/perl5/5.20/auto/nginx
/usr/lib/nginx
/usr/sbin/nginx
/usr/share/doc/nginx
/usr/share/lintian/overrides/nginx
/usr/share/nginx
/var/cache/nginx
/var/log/nginx

root@55ae1f2b1eca:/# mkdir -p /var/web/www
root@55ae1f2b1eca:/# exit
exit

[root@localhost ~]# docker cp my-nginx:/etc/nginx /var/
[root@localhost ~]# mkdir -p /var/web/www
[root@localhost ~]# cd /var/web/www/
[root@localhost www]# echo "12313123" > index.html

[root@localhost ~]# docker stop my-nginx
my-nginx
[root@localhost ~]# docker rm my-nginx
my-nginx
[root@localhost ~]# docker run -ti -d --name my-nginx -v /var/nginx:/etc/nginx -v /var/web/www:/var/web/www -p 8899:80 docker.io/nginx /bin/bash
af8a4594d643197d204200cd1e3b6a3d000cae71ef92826c0e40edfa87026a2a
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                       COMMAND             CREATED             STATUS              PORTS                           NAMES
af8a4594d643        docker.io/nginx             "/bin/bash"         52 seconds ago      Up 50 seconds       443/tcp, 0.0.0.0:8899->80/tcp   my-nginx

[root@localhost ~]# vim /etc/sysconfig/iptables
.......
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8899 -j ACCEPT

[root@localhost ~]# systemctl restart iptables.service

[root@localhost ~]# docker exec -ti my-nginx /etc/init.d/nginx start

然後就可以通過訪問http://宿主機ip:8899,進而訪問到nginx容器應用了。

接著測試下
[root@localhost ~]# mv /var/nginx/conf.d/default.conf /var/nginx/conf.d/default.conf.bak
[root@localhost ~]# cat /var/nginx/conf.d/test.conf
server {
listen 80;
server_name localhost;
location / {
root /var/web/www;
index index.html;
}
}

[root@localhost ~]# echo "12312313" > /var/www/html/test.html

接著重啟容器的nginx應用
[root@localhost ~]# docker exec -t -i my-nginx /etc/init.d/nginx restart

測試訪問(192.168.1.23是宿主機ip)
[root@localhost ~]# curl http://192.168.1.23:8899/
12313123

可以使用Nginx+Docker實現負載均衡

1)在本機部署兩個nginx的docker容器,埠對應關係分別是8088:80、8089:80
2)在本機在安裝nginx,然後在nginx配置檔案中使用upstream將訪問請求負載到本機的8088和8089埠上,
   這樣也就是將訪問請求負載到兩個容器上了

此方案的原理是將宿主機的埠和docker容器的埠做一個對映(即訪問宿主機的某埠會對映到docker容器對應的埠),
然後在宿主機通過配置Nginx,即可達到訪問宿主機的某埠,按規則分配到指定的服務地址,即完成了負載均衡。

三、tomcat容器環境部署

[root@localhost ~]# docker images
REPOSITORY           TAG                 IMAGE ID            CREATED              SIZE
docker.io/centos     latest              67591570dd29        3 months ago         191.8 MB

[root@localhost ~]# docker run -it --name=container1 docker.io/centos
[root@9df6dc740f01 /]# java -version      //容器裡安裝java
 
上傳宿主機的tomcat到容器裡
[root@localhost ~]# cd /usr/local/src/
[root@localhost src]# ls
apache-tomcat-7.0.57.tar.gz
[root@localhost src]# docker cp apache-tomcat-7.0.57.tar.gz 9df6dc740f01:/usr/local/src/
 
登陸容器,安裝tomcat
[root@9df6dc740f01 /]# cd /usr/local/src/
[root@9df6dc740f01 src]# ls
apache-tomcat-7.0.57.tar.gz
[root@9df6dc740f01 src]# tar -zvxf apache-tomcat-7.0.57.tar.gz
[root@9df6dc740f01 src]# mv apache-tomcat-7.0.57 /usr/local/tomcat7
 
將此容器提交為新的映象
[root@localhost ~]# docker commit container1 tomcat7
sha256:2ec9e2eb978a4af266608fdfd70320bff0886b245a9a2d249cdefdfe70760acb
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat7             latest              2ec9e2eb978a        3 minutes ago       562.3 MB
[root@localhost ~]# docker stop container1
container1
[root@localhost ~]# docker rm container1
container1
 
利用新提交的映象啟動tomcat容器
[root@localhost ~]# docker run -t -i -d --name=tomcat -p 8888:8080 tomcat7 /bin/bash
25f20fa6d54a1b2e2454a4d0a3966854e2fe4d81c54c366a1b07da47695f5418
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
25f20fa6d54a        tomcat7             "/bin/bash"         3 seconds ago       Up 2 seconds        0.0.0.0:8888->8080/tcp   tomcat
 
登陸容器,啟動tomcat程式
[root@localhost ~]# docker attach tomcat
[root@25f20fa6d54a ~]# /usr/local/tomcat7/bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat7
Using CATALINA_HOME:   /usr/local/tomcat7
Using CATALINA_TMPDIR: /usr/local/tomcat7/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar
Tomcat started.
[root@25f20fa6d54a ~]# ps -ef|grep tomcat
root        62     1 92 07:52 ?        00:00:03 java -Djava.util.logging.config.file=/usr/local/tomcat7/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat7/endorsed -classpath /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat7 -Dcatalina.home=/usr/local/tomcat7 -Djava.io.tmpdir=/usr/local/tomcat7/temp org.apache.catalina.startup.Bootstrap start
root        84     1  0 07:52 ?        00:00:00 grep --color=auto tomcat

宿主機防火牆開通8888埠,然後就可以在外部容器的tomcat了(通過宿主機的8888埠進行對映)

[root@localhost ~]# vim /etc/sysconfig/iptables
.......
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8888 -j ACCEPT
[root@localhost ~]# systemctl restart iptables.service

--------------------------------------------------------------------------------------------
在部署應用容器的時候,最好將容器的配置檔案及資料目錄跟宿主機目錄做個對映關係!最好不要在容器內修改資料。
這樣就可以通過宿主機的共享檔案及共享目錄去控制對應容器的資料了。
  
先啟動tomcat容器,將tomcat的配置檔案和資料目錄跟宿主機做個對映。
[root@localhost ~]# docker cp tomcat:/usr/local/tomcat7/webapps /mnt/
[root@localhost ~]# docker cp tomcat:/usr/local/tomcat7/conf /mnt/
[root@localhost ~]# ls /mnt/conf/
catalina.policy  catalina.properties  context.xml  logging.properties  server.xml  tomcat-users.xml  web.xml
[root@localhost ~]# ls /mnt/webapps/
docs  examples  host-manager  manager  ROOT
  
然後關閉和刪除這個tomcat容器,重啟啟動,啟動時做目錄對映關係
[root@localhost ~]# docker stop tomcat
tomcat
[root@localhost ~]# docker rm tomcat
tomcat
  
[root@localhost ~]# docker run -t -i -d --name=tomcat -v /mnt/webapps:/usr/local/tomcat7/webapps -v /mnt/conf:/usr/local/tomcat7/conf -p 8888:8080 tomcat7 /bin/bash
63799add4a628b1b690eb9e538001e6872b12e8e03e39b4e7275f7bf49c2645f
  
[root@localhost ~]# docker attach tomcat
[root@63799add4a62 /]# /usr/local/tomcat7/bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat7
Using CATALINA_HOME:   /usr/local/tomcat7
Using CATALINA_TMPDIR: /usr/local/tomcat7/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar
Tomcat started.
  
......................溫馨提示一下.....................
上面在建立容器時啟動的程式是/bin/bash,容器建立成功後,需要啟動建立裡其他的程式,比如上面的tomcat程式。
那麼除了上面直接登入容器內啟動tomcat程式外,還可以在宿主機上通過docker exec啟動(前提是容器在啟動狀態中)
 
docker exec 命令使用者在執行狀態中的容器內再次啟動新的程式。命令格式:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
[root@localhost ~]# docker exec tomcat /usr/local/tomcat7/bin/startup.sh   //如果啟動中出現卡的情況,就ctrl+c,不影響啟動結果
Tomcat started.

[root@linux-node2 ~]# docker attach my_tomcat
[root@f268eefdc283 /]# ps -ef|grep tomcat
root        30     0  1 10:13 ?        00:00:06 java -Djava.util.logging.config.file=/usr/local/tomcat7/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat7/endorsed -classpath /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat7 -Dcatalina.home=/usr/local/tomcat7 -Djava.io.tmpdir=/usr/local/tomcat7/temp org.apache.catalina.startup.Bootstrap start
root        76     1  0 10:23 ?        00:00:00 grep --color=auto tomcat
--------------------------------------------------------------------------------------------
如上在本機制作了tomcat7的映象,可以將這個映象上傳到別的機器上進行tomcat容器部署
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat7             latest              2ec9e2eb978a        39 minutes ago      562.3 MB
  
[root@localhost ~]# docker save tomcat7 > /opt/tomcat7.tar.gz
[root@localhost ~]# rsync -e "ssh -p22" -avpgolr /opt/tomcat7.tar.gz 192.168.1.17:/opt/
  
然後在192.168.1.17機器上部署tomcat容器
[root@linux-node2 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
tomcat7                      latest              2ec9e2eb978a        58 minutes ago      562.3 MB
[root@linux-node2 ~]# docker run -t -i -d --name=my_tomcat tomcat7 /bin/bash
8657fa536c4a6308801d96b585671a22d08795bd891b0b2b20d86b843cde0040
[root@linux-node2 ~]# docker attach my_tomcat
[root@8657fa536c4a /]# /usr/local/tomcat7/bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat7
Using CATALINA_HOME:   /usr/local/tomcat7
Using CATALINA_TMPDIR: /usr/local/tomcat7/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/tomcat7/bin/bootstrap.jar:/usr/local/tomcat7/bin/tomcat-juli.jar
Tomcat started.
--------------------------------------------------------------------------------------------

四、Mysql容器環境部署

[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    latest              67591570dd29        3 months ago        191.8 MB

啟動容器,進入容器內編譯安裝mysql
[root@localhost ~]# docker run -t -i docker.io/centos /bin/bash
[root@2ccd29e52286 /]#  rpm -qa | grep mysql       //確保沒有自帶安裝mysql,有的話就解除安裝
[root@2ccd29e52286 /]#  yum -y install make gcc-c++ cmake bison-devel ncurses-devel
[root@2ccd29e52286 /]# groupadd mysql 
[root@2ccd29e52286 /]# useradd -g mysql mysql -M -s /sbin/nologin
[root@2ccd29e52286 /]# cd /usr/local/src
[root@2ccd29e52286 src]# wget -c http://ftp.ntu.edu.tw/MySQL/Downloads/MySQL-5.6/mysql-5.6.34.tar.gz
[root@2ccd29e52286 src]# tar -zxvf mysql-5.6.34.tar.gz
[root@2ccd29e52286 src]# cd mysql-5.6.34/
[root@2ccd29e52286 mysql-5.6.34]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql/data -DSYSCONFDIR=/etc -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DWITH_READLINE=1 -DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DEXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci
[root@2ccd29e52286 mysql-5.6.34]# make && make install

[root@2ccd29e52286 mysql-5.6.34]# mkdir -p /data/mysql/data
[root@2ccd29e52286 mysql-5.6.34]# chown -R mysql:mysql /usr/local/mysql
[root@2ccd29e52286 mysql-5.6.34]# chown -R mysql:mysql /data/mysql/data

初始化mysql
[root@2ccd29e52286 mysql-5.6.34]# cd /usr/local/mysql
[root@2ccd29e52286 mysql]# ./scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/data/mysql/data --user=mysql
-------------------------------------------------------------------------------------------
如果報錯:FATAL ERROR: please install the following Perl modules before executing ./scripts/mysql_install_db: Data::Dumper

解決辦法:
[root@2ccd29e52286 mysql]# yum install -y perl-Module-Install.noarch 
------------------------------------------------------------------------------------------

啟動mysql,並設定密碼
[root@2ccd29e52286 mysql]# cp support-files/mysql.server /etc/init.d/mysql
[root@2ccd29e52286 mysql]# /etc/init.d/mysql start
[root@2ccd29e52286 mysql]# mysql -uroot
.....
修改root密碼,執行命令如下
mysql> SET PASSWORD = PASSWORD('123456');

若要設定root使用者可以遠端訪問,執行
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
使授權立即生效
mysql> FLUSH PRIVILEGES;

提交為新映象
[root@localhost ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
2ccd29e52286        docker.io/centos    "/bin/bash"         3 hours ago         Up 3 hours                              modest_bose
[root@localhost ~]# docker commit 2ccd29e52286 mysql
sha256:3b965b11e7a01b9422c8d82a8352c60c83545698309d9511b4df6371bcfcd6a1
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               latest              3b965b11e7a0        6 minutes ago       4.511 GB
docker.io/centos    latest              67591570dd29        3 months ago        191.8 MB

根據新提交的映象,啟動mysql容器
[root@localhost ~]# docker stop 2ccd29e52286
2ccd29e52286
[root@localhost ~]# docker rm 2ccd29e52286        //當然這個之前啟動的容器也可以不刪除,忽略就行。
2ccd29e52286

[root@localhost ~]# docker run -t -i -d --name=my_mysql -p 33061:3306 mysql /bin/bash
a02f56c3e7313733bcd58414d5dcd5501f8504352206ee321e9e2aeab15d6269

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
a02f56c3e731        mysql               "/bin/bash"         7 seconds ago       Up 6 seconds        0.0.0.0:33061->3306/tcp   my_mysql

啟動容器的mysql服務方法(也可以在上面建立容器的時候直接啟動,即將/bin/bash命令換成mysql啟動命令):
1)直接在宿主機上通過docker exec命令啟動
[root@localhost ~]# docker exec my_mysql /etc/init.d/mysql start        //如果啟動後出現卡的情況,就ctrl+c,不影響啟動結果
Starting MySQL SUCCESS! 
2)登陸容器內啟動
[root@localhost ~]# docker attach my_mysql
[root@a02f56c3e731 /]# /etc/init.d/mysql start
Starting MySQL SUCCESS!

檢視容器啟動的程式
[root@localhost ~]# docker top my_mysql
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                7340                28948               0                   14:21               pts/1               00:00:00            /bin/bash
root                8595                7340                0                   14:28               pts/1               00:00:00            /bin/sh /usr/local/mysql//bin/mysqld_safe --datadir=/data/mysql/data --pid-file=/data/mysql/data/mysql.pid
mysql               9376                8595                0                   14:28               pts/1               00:00:00            /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql/ --datadir=/data/mysql/data --plugin-dir=/usr/local/mysql//lib/plugin --user=mysql --log-error=/data/mysql/data/mysql-error.log --pid-file=/data/mysql/data/mysql.pid --socket=/usr/local/mysql/var/mysql.sock --port=3306

登陸容器檢視
[root@a02f56c3e731 /]# netstat -tunlp         //首先yum安裝net-tools
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      -   

在容器內的mysql裡寫入一些資料
[root@a02f56c3e731 /]# /usr/local/mysql/bin/mysql -p123456
Warning: Using a password on the command line interface can be insecure.
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)

[root@a02f56c3e731 /]# ln -s /usr/local/mysql/var/mysql.sock  /var/lib/mysql/mysql.sock
ln: failed to create symbolic link '/var/lib/mysql/mysql.sock': File exists
[root@a02f56c3e731 /]# rm -f /var/lib/mysql/mysql.sock
[root@a02f56c3e731 /]# ln -s /usr/local/mysql/var/mysql.sock  /var/lib/mysql/mysql.sock

[root@a02f56c3e731 /]# /usr/local/mysql/bin/mysql -p123456
.......
mysql> create database wangshibo;
Query OK, 1 row affected (0.00 sec)

mysql> use wangshibo;
Database changed
mysql> create table hehe(
    -> id int(3),
    -> name varchar(10)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into hehe values(1,"wanglei");
Query OK, 1 row affected (0.01 sec)

mysql> insert into hehe values(2,"zhaomin");
Query OK, 1 row affected (0.01 sec)


檢視容器ip,可以登陸容器內ifconfig檢視(首先要yum安裝net-tools)
[root@a02f56c3e731 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 117  bytes 319373 (311.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 102  bytes 7042 (6.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

或者在宿主機使用docker inspect命令檢視容器ip
[root@localhost ~]# docker inspect my_mysql|grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",


在宿主機本地連線容器的mysql
[root@localhost ~]# mysql -u root -h 172.17.0.2 -p123456
ERROR 1130 (HY000): Host '172.17.0.1' is not allowed to connect to this MySQL server
出現錯誤的原因:
容器的網路ip是根據宿主機的虛擬橋接網路卡docker0自動分配的,而docker0的ip預設是172.17.0.1.
容器的mysql內需要給這個ip授權。
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
..........

登陸容器內的mysql,進行授權
[root@a02f56c3e731 /]# /usr/local/mysql/bin/mysql -p123456
.......
mysql> select host,user,password from mysql.user;
+--------------+------+-------------------------------------------+
| host         | user | password                                  |
+--------------+------+-------------------------------------------+
| localhost    | root | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| 2ccd29e52286 | root |                                           |
| 127.0.0.1    | root |                                           |
| ::1          | root |                                           |
| localhost    |      |                                           |
| 2ccd29e52286 |      |                                           |
+--------------+------+-------------------------------------------+
6 rows in set (0.00 sec)

mysql> grant all privileges on *.* to root@'%' identified by "123456";
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> select host,user,password from mysql.user;
+--------------+------+-------------------------------------------+
| host         | user | password                                  |
+--------------+------+-------------------------------------------+
| localhost    | root | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| 2ccd29e52286 | root |                                           |
| 127.0.0.1    | root |                                           |
| ::1          | root |                                           |
| localhost    |      |                                           |
| 2ccd29e52286 |      |                                           |
| %            | root | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
+--------------+------+-------------------------------------------+
8 rows in set (0.00 sec)

再次在宿主機本機嘗試連線容器的mysql,發現可以正常連線!
[root@localhost ~]# mysql -u root -h 172.17.0.2 -p123456
.......
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| wangshibo          |
+--------------------+
5 rows in set (0.01 sec)

MySQL [(none)]> select * from wangshibo.hehe;
+------+---------+
| id   | name    |
+------+---------+
|    1 | wanglei |
|    2 | zhaomin |
+------+---------+
2 rows in set (0.00 sec)


---------------------------------------------------------------------------------------------------
也可以再建立一個容器,使用--link進行容器連結。
這裡需要特別注意一下"--link=my_mysql:mydb"(中間可以使用=,也可以空格隔開),這個引數是告訴容器需要使用my_mysql容器,並將其別名命名為mydb,這樣在這兩個容器裡就可以使用mydb來作為提供mysql資料庫服務的機器名。
[root@localhost ~]#  docker run --rm -it --name mymysql2 --link my_mysql:mydb docker.io/centos /bin/bash
[root@f1534ad473f4 /]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  mydb 33d784ee3121 my_mysql
172.17.0.4  f1534ad473f4

[root@f1534ad473f4 /]# mysql -u root -h mydb -p123456
......
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| wangshibo          |
+--------------------+
5 rows in set (0.00 sec)

MySQL [(none)]> select * from wangshibo.hehe;
+------+---------+
| id   | name    |
+------+---------+
|    1 | wanglei |
|    2 | zhaomin |
+------+---------+
2 rows in set (0.00 sec)

------------------------------------------------------------------------------------------------

在外部連線my_mysql容器內的mysql,就需要通過對映到宿主機的33061埠了(首先在宿主機的iptables裡開放33061埠的訪問)
[root@localhost ~]# vim /etc/sysconfig/iptables
......
-A INPUT -p tcp -m state --state NEW -m tcp --dport 33061 -j ACCEPT
[root@localhost ~]# systemctl restart iptables.service 

這樣在遠端,就可以使用宿主機的對映埠33061訪問容器mysql (使用-P指定埠進行mysql的連線)
[root@huanqiu_web1 ~]# mysql -uroot -h103.10.86.23 -P33061 -p123456
.......
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| wangshibo          |
+--------------------+
5 rows in set (0.00 sec)

mysql> select * from wangshibo.hehe;
+------+---------+
| id   | name    |
+------+---------+
|    1 | wanglei |
|    2 | zhaomin |
+------+---------+
2 rows in set (0.00 sec)

mysql> 

----------------------------------------------------------------------------------------
上面容器內使用的是編譯安裝mysql,也可以yum安裝:

[root@localhost ~]# docker run -t -i --privileged -i --name=wang docker.io/centos /sbin/init     //容器啟動後,會一直在卡著的狀態中,先不用管,開啟另一個終端視窗執行下面命令登陸容器
[root@localhost ~]# docker exec -it wang /bin/bash
[root@e9efd323782a /]# yum install -y wget net-tools
[root@e9efd323782a /]# wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
[root@e9efd323782a /]# rpm -ivh mysql-community-release-el7-5.noarch.rpm
[root@e9efd323782a /]# yum install mysql-community-server
[root@e9efd323782a /]# systemctl start mysqld
[root@e9efd323782a /]# lsof -i:3306
COMMAND PID  USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
mysqld  453 mysql   10u  IPv6 32200473      0t0  TCP *:mysql (LISTEN)

其他應用容器的部署與上面操作類似~

相關文章