Docker的網絡通信與數據共享與docker-compose

一、容器之間通信

1、單向通信

1.1、什麼意思

在這裏插入圖片描述

mysql和tomcat是兩個獨立的容器,但是tomcat需要和mysql通信,而mysql完全不用和tomcat通信,這就叫容器之間的單向通信。

1.2、怎麼通信

要談通信,就需要談一下ip,因爲不知道ip是無法通信的。最簡單的例子你jdbc要連接mysql數據庫,你也需要配置mysql的ip地址。容器之間也不例外,都是靠虛擬ip來完成的。

何爲虛擬ip?

虛擬ip:容器創建完成後都會生成一個唯一的ip,這個ip外界不能直接訪問,他只用於容器之間進行通信交互用。這就是虛擬ip。

容器之間的虛擬ip是互通的。

通信是什麼意思、靠什麼通信我們都知道了,那還不抓緊實戰一把?

1.3、實戰演示

1.3.1、創建tomcat容器

docker run -d --name mytomcat tomcat
# --name指定的名稱再docker ps裏是可以看到的,最後一列Name
docker ps

知識點出現了!!! --name是神馬鬼? 先看如下一個場景

在公司或者你直接買的阿里雲數據庫/redis等服務爲什麼給你個數據庫域名而不是推薦用ip?因爲ip的話可變,比如你業務系統寫死了ip,這時候人家那邊內網ip變了,你這所有用這個數據庫的業務系統都要跟着改。用域名的話一勞永逸,底層ip變了後再映射到新域名上就行,不影響業務系統。

–name就是給docker配置名稱來與虛擬ip做映射,因爲ip老變化,每次變化的時候其他容器都需要跟着改動才行。配個名稱一勞永逸。創建容器的時候通過 --name xxx 即可指定。

1.3.2、創建mysql容器

我也沒拉取mysql鏡像,就用centos模擬一下數據庫吧,主要是看能不能ping 通,能ping 通就代表能通信。

docker run -d --name database -it centos /bin/bash

1.3.3、小試一把

我們需要進入mytomcat的容器然後去ping database的ip看看是否通,那麼容器的虛擬ip怎麼查呢?

# 這又是一個知識點
docker inspect 容器id
# 比如:(9bf58b4014dd是我們database的容器id)
docker inspect 9bf58b4014dd

在這裏插入圖片描述

現在知道數據庫的ip了,那趕緊進入我們的mytomcat的容器去ping一波

docker exec -it mytomcat /bin/bash
ping 172.17.0.6

在這裏插入圖片描述

完美!

等等,貌似不是很完美,我們給數據庫指定了名稱database,那我們趕緊ping database 試一下。結果啪啪啪打臉,完全不通,那是因爲相當於你就起了個名字,並沒有做映射。那怎麼映射呢?mytomcat啓動容器的時候指定一個–link參數即可。

# 強制刪除老的
docker rm -f mytomcat
# 創建新的容器,用--link指定我們想連的配置的數據庫“域名”
docker run -d --name mytomcat --link database tomcat
# 進入mytomcat容器
docker exec -it mytomcat /bin/bash
# ping
ping database

在這裏插入圖片描述

這次是真的完美~!

1.4、總結

  • 容器簡單虛擬ip是互通的
  • 用–name 和 --link可以完成自定義“域名”來取代可變化的ip

2、雙向通信

方式有很多,一般都採取橋接方式。由於篇幅過長,自行Google即可。重點搞懂了容器間的通信是什麼意思,大概怎麼做即可。比如上面的–link也是其一做法。

二、容器間數據共享

1、場景

需要宿主機和容器之間共享數據的業務場景。比如Mysql的

比如:集羣部署的時候,我們的應用程序需要部署到10個docker容器裏,那麼比如要想改動一個文件的內容,就要重新打包然後部署10次。我們可以將我們需要部署的應用程序掛載到宿主機上,這樣改一處就行了。比如靜態html文件,再一個宿主機上啓動了10個容器,這時候需求需要改文案(修改html),我們需要修改10個容器裏的html,過於麻煩,所以可以把這個html掛載到宿主機,容器直接使用掛載到宿主機的文件即可。

再比如:Mysql的數據目錄可配置文件(一些高級配置或者優化配置啥的肯定要用一份),這也可以用此場景。

2、語法

# 語法
docker run -v 宿主機路徑:容器內掛載路徑 鏡像名
# 比如如下:他會把/home/main/programe下面的所有目錄都掛載到容器的/usr/local/tomcat/webapps下
docker run -v /home/main/programe:/usr/local/tomcat/webapps tomcat

3、實戰

3.1、準備

在如下目錄裏創建如下文件,並寫上Hello Volumn~

/home/main/docker/webapps/volumn-test/index.html

3.2、操作

很簡單,按照上面的語法來就成了,如下就是將/home/main/docker/webapps下的目錄掛載到容器內部/usr/local/tomcat/webapps的目錄下

docker run --name t2 -d -p 8200:8080 -v /home/main/docker/webapps:/usr/local/tomcat/webapps tomcat

3.3、驗證

我們先進入容器

docker exec -it t2 /bin/bash

然後查看/usr/local/tomcat/webapps下是否有我們掛載的目錄以及文件

root@4be396ff443b:/usr/local/tomcat/webapps# ls -R volumn-test/
volumn-test/:
index.html

最後我們訪問下看看效果

[root@izm5 volumn-test]# curl 'localhost:8200/volumn-test/index.html'
Hello Volumn~~

我們修改下宿主機上的index.html的內容,修改爲Hello Volumn~~ How are you?然後再次訪問看效果:

這裏修改的是宿主機/home/main/docker/webapps/volumn-test下的index.html,爲不是容器內部的。

[root@izm5 volumn-test]# curl 'localhost:8200/volumn-test/index.html'
Hello Volumn~~ How are you?

很完美,容器無感知的就生效了。

3.4、好處

我這是啓動了一個容器舉例,如果多啓動幾個呢?然後產品要修改文案,那麼你登錄每個容器裏去修改?或者重新打包然後重新啓動所有容器?有點小題大做呀,利用-v命令進行掛載實現宿主機和容器的數據共享她不香嗎?

4、新的問題

如果容器過多,那麼每次啓動容器都要-v xxx:xxx,這也很容易寫錯啊,寫錯一個字母都不行,還有,如果宿主機換地址了,這也需要批量更換容器的docker run -v的參數,機器太多不利於維護。

5、解決問題

共享容器誕生了!

5.1、共享容器概念

如果容器太多,每一次都要寫-v xxx:xxx,過於複雜,也容易出錯,這時候可以通過docker create創建共享容器,然後啓動的時候通過--volumes-from指定創建的共享容器名稱即可,也就是說可以把上面-v xxx:xxx這一串統一放到一個地方去管理,容器啓動的時候直接引用這個統一配置即可,方便統一管理。

5.2、語法

# 創建共享容器語法,只是創建不是啓動。最後的/bin/true 就是一個佔位符,沒啥亂用。
docker create --name 共享容器名稱 -v 宿主機路徑:容器內掛載路徑 鏡像名稱 /bin/true
# 啓動容器的時候通過--volumes-from 共享容器名稱來使用共享容器掛載點
docker run --volumes-from 共享容器名稱 --name xxx -d 鏡像名稱

5.3、實戰

# 創建共享容器
docker create --name webpage -v /home/main/docker/webapps:/usr/local/tomcat/webapps tomcat /bin/true
# 採取共享容器的配置來啓動容器
docker run -p 8300:8080 --volumes-from webpage --name t3 -d tomcat
# 在啓動個
docker run -p 8400:8080 --volumes-from webpage --name t4 -d tomcat

5.4、驗證&&好處

驗證跟第一種-v的方式一樣,修改內容,容器無感知。

相對於第一種方式的好處是:

  • 不用每次都寫-v xxx:xxx這一長串不僅令人厭惡還容易出現錯誤的英文字母。
  • 更改路徑,只修改一處即可。

三、DockerCompose

1、有什麼用

比如我們要部署一個javaweb應用,那一般情況都需要三個容器:nginx容器、tomcat容器、mysql容器。這是最基本的,可能更復雜。那運維人員每次都需要單獨啓動這三個容器來支撐我們的web應用嗎?有點複雜了。docker-compose就是爲了簡化這個過程的,相當於是個腳本,把這三個容器用腳本統一來管理和啓動。節省運維時間和避免出錯率。也就是說多應用互相協同才能完成一件事的時候,是很好用的,否則直接Dockerfile就完了。

2、安裝DockerCompose

基於Linux的安裝。

參考的官方安裝文檔:https://docs.docker.com/compose/install/

執行如下兩個命令就完事了:

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

如果第一個命令特別慢的話可以用如下命令代替,畢竟是國外網站

curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

安裝完進行驗證:

docker-compose --version

3、實戰感受一下

先來感受一下docker-compose的威力,部署下WordPress來玩玩。不知道WordPress是啥的自己百度,就是一個開源博客。

爲什麼是部署WordPress,因爲官方也是WordPress…面向官方文檔學習…

官方文檔安裝WordPress的教程:https://docs.docker.com/compose/wordpress/

(1)建立如下目錄

/home/main/docker/WordPress

(2)建立docker-compose.yml文件

cd /home/main/docker/WordPress
vi docker-compose.yml

(3)在docker-compose.yml裏寫上如下內容

version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}

看不懂?正常,也沒關係。這就是大名鼎鼎的docker-compose,就是一個一.yml爲後綴結尾的腳本文件。他能自動幫我們部署我們配置的容器,比如上述有mysql容器和wordpress容器。我們還能看到端口是8000,這就夠了。開幹!

(4)執行腳本

# 先進入你的docker-compose.yml所在的目錄
cd /home/main/docker/WordPress
# 執行腳本
docker-compose up -d

(5)結果分析

[root@izm5e3qug7oee4q1y4opibz WordPress]# docker-compose up -d
Creating network "wordpress_default" with the default driver
Creating volume "wordpress_db_data" with default driver
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
afb6ec6fdc1c: Pull complete
....
0bdc5971ba40: Pull complete
Digest: sha256:d16d9ef7a4ecb29efcd1ba46d5a82bda3c28bd18c0f1e3b86ba54816211e1ac4
Status: Downloaded newer image for mysql:5.7
Pulling wordpress (wordpress:latest)...
latest: Pulling from library/wordpress
afb6ec6fdc1c: Already exists
3d895574014b: Pull complete
...
Digest: sha256:0b452b7b45fa770f12e864720abb01bef506f4abe273669402434e94323c97d7
Status: Downloaded newer image for wordpress:latest
Creating wordpress_db_1 ... done
Creating wordpress_wordpress_1 ... done

可以看到pulling db、pulling wordpress、done。大概瞭解到爲我們創建了wordpress和wordpress所需要的mysql數據庫。訪問8000端口,大功告成!
在這裏插入圖片描述

4、和Dockerfile區別

Dockerfile容器間通信需要–link或者橋接方式進行,而DockerCompose全自動的呀。也就是說單容器的話肯定Dockerfile了,但是多容器之間需要交互、有依賴關係,那用DockerCompose來統一管理那些零散的Dockerfile來達到自動構建部署的一體化腳本。

5、實戰

5.1、需求描述

實戰一個spring boot的項目,一個springboot的jar包依賴mysql數據庫。我們用docker-compose完成自動化部署。

5.2、準備工作

5.2.1、 準備如下文件

[root@izm5e3qug7oee4q1y4opibz docker-compose-app]# pwd
/home/main/docker/docker-compose-app
[root@izm5e3qug7oee4q1y4opibz docker-compose-app]# ls -l
total 12
drwxr-xr-x 2 root root 4096 May 24 12:20 app
drwxr-xr-x 2 root root 4096 May 24 12:20 db
-rw-r--r-- 1 root root  335 May 24 12:20 docker-compose.yml

5.2.2、app

裏面就是我們的springboot的jar包和製作鏡像的Dockerfile文件。

[root@izm5e3qug7oee4q1y4opibz docker-compose-app]# ll app/
total 23492
-rw-r--r-- 1 root root     1071 May 24 12:19 application-dev.yml
-rw-r--r-- 1 root root     1457 May 24 12:19 application.yml
-rw-r--r-- 1 root root 24042957 May 24 12:20 bsbdj.jar
-rw-r--r-- 1 root root      154 May 24 12:20 Dockerfile

看下application-dev.yml的配置,主要看數據庫配置:

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://db:3306/bsbdj?useUnicode=true
    username: root
    password: root
    tomcat:
      init-s-q-l: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
server:
  port: 80

這裏我們發現貓膩了,數據庫配置是db:3306,這不是平常的ip/域名神馬的,這個是Mysql容器名稱。所以這個服務依賴mysql服務,所以我們的主要目的就是利用DockerCompose來自動化操作多容器的Dockerfile文件來自動部署和初始化SQL的操作。

5.2.3、db

jar包所需要的數據庫的sql文件和製作鏡像的Dockerfile文件。

[root@izm5e3qug7oee4q1y4opibz docker-compose-app]# ll db/
total 35612
-rw-r--r-- 1 root root       69 May 24 12:20 Dockerfile
-rw-r--r-- 1 root root 36460577 May 24 12:20 init-db.sql

5.3、開始實戰

5.3.1、app的Dockerfile

FROM openjdk:8u222-jre
WORKDIR /usr/local/bsbdj
ADD bsbdj.jar .
ADD application.yml .
ADD application-dev.yml .
EXPOSE 80
CMD ["java","-jar","bsbdj.jar"]

5.3.2、db的Dockerfile

FROM mysql:5.7
WORKDIR /docker-entrypoint-initdb.d
ADD init-db.sql .

這裏有個細節:爲什麼是進入docker-entrypoint-initdb.d這目錄在ADD sql?因爲這個目錄是個後門,這個目錄下的sql文件會自動執行。我咋知道的?官方告訴我的:
https://hub.docker.com/_/mysql
在這裏插入圖片描述

5.3.3、最終Boss:docker-compose.yml

現在我們應用程序的Dockerfile和應用程序所依賴的數據庫Dockerfile都已就緒。還剩下最後一個終極yml配置文件

# 目前最穩定版本:3.3,所以3.3就行。
version: '3.3'
services:
  ## 服務名稱叫 db,還記得我們application-dev.yml的配置嗎?數據庫配置的是db,對應的就是這裏了。
  db:
    # Dockerfile文件所屬的目錄。
    build: ./db/
    # always:宕機自動重啓。牛逼的很。
    restart: always
    # 環境變量,類似於-e參數
    environment:
      MYSQL_ROOT_PASSWORD: root
  # 服務名稱叫 app    
  app:
    # Dockerfile文件所屬的目錄。若app依賴db,則需要把db服務配置放到app的前面。
    build: ./app/
    # 依賴上面的db service
    depends_on:
      - db
    # 宿主機和容器的端口均爲80。上面app的Dockerfile暴露的是80端口,所以這裏容器是80  
    ports:
      - "80:80"
    restart: always

5.3.4、啓動

# -d代表後臺啓動
docker-compose up -d

啓動結果:

[root@izm5e3qug7oee4q1y4opibz docker-compose-app]# docker-compose up -d
Creating network "docker-compose-app_default" with the default driver
Building db
Step 1/3 : FROM mysql:5.7
 ---> a4fdfd462add
Step 2/3 : WORKDIR /docker-entrypoint-initdb.d
 ---> Running in d1ff6e4bb5a8
Removing intermediate container d1ff6e4bb5a8
 ---> d29a05c5bfcb
Step 3/3 : ADD init-db.sql .
 ---> 6ae6d9eb35ca

Successfully built 6ae6d9eb35ca
Successfully tagged docker-compose-app_db:latest
WARNING: Image for service db was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Building app
Step 1/7 : FROM openjdk:8u222-jre
8u222-jre: Pulling from library/openjdk
9a0b0ce99936: Pull complete
db3b6004c61a: Pull complete
f8f075920295: Pull complete
4901756f2337: Pull complete
9cfcf0e1f584: Pull complete
d6307286bdcd: Pull complete
Digest: sha256:3d3df6a0e485f9c38236eaa795fc4d2e8b8d0f9305051c1e4f7fbca71129b06a
Status: Downloaded newer image for openjdk:8u222-jre
 ---> 25073ded58d2
Step 2/7 : WORKDIR /usr/local/bsbdj
 ---> Running in df4a4c352e71
Removing intermediate container df4a4c352e71
 ---> 0d88b2f13319
Step 3/7 : ADD bsbdj.jar .
 ---> aabaa119855d
Step 4/7 : ADD application.yml .
 ---> 7e1f7b4614cc
Step 5/7 : ADD application-dev.yml .
 ---> a8d36115592f
Step 6/7 : EXPOSE 80
 ---> Running in 26b44c9d57ef
Removing intermediate container 26b44c9d57ef
 ---> fd36f3cdd115
Step 7/7 : CMD ["java","-jar","bsbdj.jar"]
 ---> Running in 64bdeff2f1ce
Removing intermediate container 64bdeff2f1ce
 ---> 77d18bae9bbc

Successfully built 77d18bae9bbc
Successfully tagged docker-compose-app_app:latest
Creating docker-compose-app_db_1 ... done
Creating docker-compose-app_app_1 ... done

可以看到先爲我們構建了mysql的鏡像然後又構建了bsbdj.jar的鏡像。最後執行了CMD ["java","-jar","bsbdj.jar"],這些過程全自動化。

查看容器

docker-compose ps

結果:

[root@izm5e3qug7oee4q1y4opibz docker-compose-app]# docker-compose ps
          Name                       Command             State          Ports       
------------------------------------------------------------------------------------
docker-compose-app_app_1   java -jar bsbdj.jar           Up      0.0.0.0:80->80/tcp 
docker-compose-app_db_1    docker-entrypoint.sh mysqld   Up      3306/tcp, 33060/tcp

然後訪問http://ip:80即可看到效果。

6、補充

docker-compose其他命令可以用docker-compose --help查看。再說下docker-compose和Dockerfile區別,可以粗糙理解成Dockerfile是針對單容器的腳本,docker-compose是針對多Dockerfile的自動化腳本,他幫我們處理容器之間的依賴關係和其他需要人爲干涉的操作。

四、答疑

1.ADD命令能否解壓zip格式?多模塊該怎麼創建鏡像?

ADD命令不能解壓zip,親測。能解壓:tar, gzip, bzip2, etc。

多模塊恰巧是今天的主角docker-compose,可以爲每一個模塊都書寫一個Dockerfile,然後用docker-compose去管理這些帶有依賴關係的模塊。

如果是集羣的話,首選k8s,docker warm什麼的,畢竟docker-compose致命缺點僅限在單機上。

2.有了docker commit爲啥還要Dockerfile?

docker commit都是黑箱操作,過一段時間後自己都不知道這個鏡像是怎麼做出來的,都安裝了什麼。但是使用Dockerfile構建的鏡像,我們能清楚的知道都有哪一層,每層是幹嘛的,修改也方便,易於維護。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章