Docker 簡介

包括:
一. Docker 介紹
二. Docker 網絡配置(容器互聯*) 和 Dockerfile 
三. Docker 的一些常用命令
四. Docker 的實際部署
五. 一些坑 總結


一. Docker 介紹
1.1 基本概念
          Docker 是由 Go 語言編寫,一個快速部署的 輕量級虛擬技術項目,它允許開發人員把自己的程序 和 開發環境一起打包,製作成一個 Docker 的image(鏡像),這樣部署到服務器上,也只需要下載這個 image 鏡像將程序跑起來,免去了每次安裝依賴和環境的麻煩,還能做到應用間的隔離。
          Docker 系統有兩個程序,服務器端 和 客戶端。服務器端 是一個服務進程,管理所有容器。客戶端 相當於服務器端的遠程控制器。

爲什麼要用Docker:
  • 對系統資源利用率高:一個主機可以運行上千個 Docker。基本不消耗資源,傳統的虛擬機的方式,10個 不同的應用就要起10個虛擬機,而Docker 只需要啓動 10 個 隔離的應用即可。
  • Docker 容器幾乎可以在任何平臺上跑,比較容易遷移。
  • 啓動快。
  •  …...

1.2 鏡像,容器,倉庫
Docker 有三大概念: 鏡像(image),容器(container),倉庫。
  • 鏡像:可以用來創建 Docker 容器(container)。
  • 容器:是鏡像 創建的運行實例。可以被啓動,開始,停止,刪除。每個容器相互隔離,保證安全。容器可以看成是簡易版的 Linux 環境,並且鏡像 是 只讀的,容器可以創建一層可寫層作爲最上層。
  • 倉庫:是存放鏡像文件的場所。倉庫註冊服務器包括多個倉庫,每個倉庫又包括了 多個鏡像。倉庫又分爲公開倉庫 和 私有倉庫,最大的公開倉庫是 Docker Hub。(可以理解成 github 這樣的)

          總的來說,我們可以把 運行的操作系統(比如 ubuntu,centos),環境(比如 java,mysql,tomcat),應用程序(自己的代碼)等打包成一個 image,然後 就可以 執行 run,那麼 就變成一個 container,此時我們設置一些命令,也可以說是腳本,那麼應用就可以跑起來了。
          並且,這個 image 可以複用,比如說我有另外一個程序,也是用這套環境,那麼我就不用再重新搭建環境了,直接用這個 image 即可。
          除此之外, 外部能不能訪問我這個container,都可以通過網絡設置來控制,比如說,我的 mysql 跑在一個 container 中,我不想讓外部訪問我的 mysql,只能讓另外一個 container 訪問(也就是我的應用程序), 那麼也是可以做到。 這就是 docker 的一個 隔離機制。
          最後,container 之間是 也是相互不影響的。
          這也是 docker 的一些好處。

二. Docker 網絡配置 和 Dockerfile 

2.1 Docker 網絡配置 :

          如下圖所示: 一個 Docker 中可以 開多個 container,每個 container 其實可以理解成獨立的 一個服務器,即可以讓別人訪問,也可以不讓別人訪問。
          當需要給別人訪問的時候,這個 別人分爲兩種,一種 是 其他的 container,一種是 public(即外部 + 其他container)。具體怎麼設置,下文再說。從這個圖可以看出,Docker 更適合於 分佈式的應用,把不同的服務 放在 不同的 container 中,彼此可以相互的訪問,並且可以設置外部訪問不了。 同時,這些 服務相互不影響,可以各自用各自的環境,比如說一個 用 centos 系統,另外一箇中 ubuntu系統,一個 用mysql 數據庫,一個用 redis,等等。
          下圖中,可以在docker run images 的時候(也就是 把container 啓動的時候) 設置好 80:8080 ,表示 外部如果訪問 本機的 80端口,那麼 會轉向開放了 8080 端口的 container1 中。如果container1 沒有開放任何 端口,那麼container1 誰也訪問不了(包括其他container)。 


          上面說的80:8080 可以用下面這個圖再解釋一下: 

          也就是說,本來主機有操作系統 centos,外部可以訪問這個主機的端口。此時,這個主機又開了多個 container,這些container 也是系統,同樣,他們也有端口,所以就涉及到 主機的端口轉到 內部 container 的系統的端口。可以聯想下 虛擬機 和 nginx 的轉發。

容器互聯:
          容器互聯是個 Docker 比較重要的知識。
          使用 - - link 是參數可以讓容器之間 安全的進行交互。格式爲 - - link name:alias   name表示要鏈接的容器的名稱,alias 表示 這個鏈接的別名。 
          Docker 在兩個互聯的容器之間創建了一條安全隧道,而且不用映射他們的端口到宿主主機上。在啓動 db 容器的時候並沒有使用 -p 或者 -P 標記,從而避免暴露了數據庫端口到外部網絡上。 

具體如何進行容器間互聯:
  1. 定義一個 A 容器 :比如說 docker run -it  - -name  “container1”       //注意,一定要定義這個名字,下面要用到
  2. 定義一個 B 容器 並且鏈接A 容器 :比如說 docker run -it - -name “container2” - -link container1:xxx  images
完成鏈接。
QA:
  1. 第二句怎麼理解:docker run -it 就不說了,正常的docker啓動。  - -name 就是指定 這個container 叫什麼名字。 - -link  表示我要進行container 互聯,固定的。 container1:xx  表示 我要連哪個 container, xx 表示 別名,你可以理解爲這個鏈接的名字是什麼。
  2.  怎麼知道連OK了? 用第二個container 鏈接第一個 container ,那麼去到第二個container 中,vi /etc/hosts 你就會發現連OK了。如下圖是我連好了的:

          這個hosts 文件 看最後一行,就是表示 我連上了 名字爲 kong_test1 的container,這個kong_test1 的container 的IP 是 172.17.0.3(自己的看第一行是 172.17.0.6),這個kong_test1 的 container id 是 56efdfefe3bb。這個鏈接的名稱爲 KConnection。
          最後你可以ping 一下 173.17.0.3 ,你會發現是通的。 


2.2 dockerfile :
          創建 images 有兩種方式。
  1. 下載好別人的 image(也就是別人做好的環境),跑起來,此時變成了一個 container,然後在它的環境的基礎上安裝自己的一些東西。最後在 docker commit ,就會把這個 環境打包成一個 image。這個image 實際上就是別人的image+自己定製的部分。
  2. 使用docker file,這是一個文件,裏面會有一行一行的命令, 直接用docker build,然後docker 就會執行這些命令,生成一個 image。那麼 這些命令是什麼,下面介紹。

例如如下是一個 我在阿里雲上 測試的 dockerfile: 
FROM 9114c29f37a8

MAINTAINER wuhuachuan [email protected]

COPY ./tomcat8/ /home/whc/tomcat/

CMD bash /home/whc/tomcat/apache-tomcat-8.0.27/bin/startup.sh && tail -f /home/whc/tomcat/apache-tomcat-8.0.27/logs/catalina.out

這4行的意思是:
  1. FROM:這個指令一開始必須要有,表示你的image 是基於什麼image的。一般來說,我們最最開始的可以基於一個 centos系統的 image。
  2. MAINTAINER :告訴別人你的大名。
  3. 表示我要把 當前目錄的 tomcat 的文件 複製到 container 中的 /home/whc/tomcat 目錄中。當前 這個意思就是你現在在的這個系統,等你運行的時候,container 也會是一個在你係統內部的系統,這行的意思就是 複製到你 這個 container 系統中去。
  4. CMD :表示 當我的container 啓動的時候,會幫我 自動運行bash …./startip.sh 和 tail … /catalina.out 這兩個命令。其實這兩個命令就是 啓動tomcat 的意思。
所以說,這四行就可以創建一個 簡單的 image,並且在啓動的時候 會自動運行 tomcat,如果我們在web 程序放入到 tomcat 的 webapps 目錄下,那麼實際上就是 跑了我們的程序的意思。

          以上告訴一些大體的概念,細節暫時不用糾結。


三. Docker 的一些常用命令

3.1 運行 image
  1. 先用 docker ps -a 看看有沒有容器,如果已經存在容器,那麼使用 docker start  容器ID,即可。
  2. docker run -it a38c26f8f4b8 :docker run 是固定的,-it 表示 你運行後,會進入到 該 container 的終端,(Ps,你現在是在本機的終端中),這個數字就是表示 image 的 id。
  3. docker run -d  a38c26f8f4b8 :-d 表示運行了 這個 image,但是是後臺運行,不會進入到該container 的終端,還是在現在這個系統的終端。
  4. docker run - -rm a38c26f8f4b8 :- - rm 表示 當裏面的container 退出之後,該容器會自動刪除。
  5. docker run -d -p 80:8080 a38c26f8f4b8 :其中 -p 80:8080 表示,當這個容器啓動的時候,會開放8080 端口給外部docker。那麼當有人請求 80 端口的時候,docker 就會把 80 轉到 8080 端口,也就是我們的這個 容器中。如果裏面有 tomcat 監聽了8080 端口,那麼實際上就是訪問了 這個容器的 tomcat。

3.2 查看
  1. 查看目前有什麼鏡像:docker images。
  2. 查看目前正在運行的容器:docker ps。查看有什麼容器: docker ps -a。

3.3 刪除
  1. 刪除容器: 先用 docker ps -a 查看容器的 id。然後執行 docker rm 容器Id。(Ps:如果容器還在運行,需要先運用 docker stop 容器ID,把這個容器先停掉。)
  2. 刪除鏡像:docker rmi 鏡像ID。

3.4 創建鏡像
          按照上面提到的方式,有兩種創建方法:
  1. docker commit -m “創建註釋” -a “你的用戶名字”  容器ID 鏡像倉庫:標籤。具體示例如下:
    1. docker commit -m “centos 加入了 java8鏡像” -a “wuhuachuan” 8fa5fa9ba7f0 wuhuachuang/whc:centos-java8  這個表示 我的名字是 wuhuachuan,我的倉庫 wuhuachuan/whc,標籤是 centos-java8.
  2. 第二種創建方式是 使用 docker build -t ”wuhuachuan/whc:centos-java8” .  其中 有一個 點 ,表示 dockerfile在當前的目錄中 。

3.5 暴露端口

          主要有 EXPOSE 和 -p/-P 兩種方式,EXPOSE 是寫在dockerfile 中, -p/-P 的方式是 在 docker run  的時候指定的。具體關於 怎麼暴露,stackoverflow 上有一個 很好的解釋: 




簡單翻譯下:
  • 如果你 不指定 EXPOSE  和 -p 那麼 container 裏面的服務 container 外部是肯定訪問不了。
  • 如果你 EXPOSE 一個端口,service 裏面的服務外面肯定是訪問不了,但是其他容器可以訪問。所以說這是容器互聯這是比較好的方式。
  • 如果 你 EXPOSE 和 -p 一個端口,那麼哪裏都可以訪問。
  • 如果你使用了 -p 不使用 EXPOSE 。docker 會有一個默認的 EXPOSE。也是哪裏都可以訪問。


四. Docker 的實際部署

          說下我目前在 阿里雲上 做了的事情:
  1. 安裝docker。
  2. 寫dockerfile,如上的 dockerfile 代碼。
  3. 執行 docker build。(具體如上代碼) 。生成一個鏡像。
  4. 執行 docker run -d  -p 80:8080 imageID。運行鏡像,生成container,啓動tomcat。
  5. 完。

          當然,中間由於學習的時候不懂 ,使用了無數次docker ps -a, docker images,docker rm,docker rmi 等命令。還是自己敲記憶深。

如下賦上 我工作時 生產環境下的 Dockerfile:
FROM ubuntu
ADD jdk-8u51-linux-x64.tar.gz /opt/
ADD dsc-cassandra-2.1.11-bin.tar.gz /opt/
ADD kong-0.5.4.trusty_all.deb /opt/
ENV JAVA_HOME=/opt/jdk1.8.0_51
ENV PATH=$JAVA_HOME/bin:$PATH
RUN apt-get update && apt-get install -y \
    dnsmasq-base \
    dnsmasq \
    openssl \
    curl
RUN dpkg -i /opt/kong-0.5.4.trusty_all.deb
EXPOSE 8000

       總體的意思是,基於 ubuntu,首先把 jdk,cassandra 數據庫,kong 文件複製進去,然後設置環境變量,安裝一些軟件,安裝我的kong,開放 8000 端口給內部 container 使用。(Kong 是什麼可以參考另外一篇博文 微服務那個)



五. 一些坑 總結
  1. Tomcat 的啓動
          容器運行完之後,就會自動退出,tomcat 的啓動那麼 以deamon 線程跑,docker 就會認爲已經運行完了,那麼就會退出,所以說tomcat 啓動一會就會掛掉。(其實是整個 容器退出了,因爲docker 認爲結束了)。此時的解決辦法 就是讓 docker 認爲 容器的任務還沒有結束,可以使用如下: 



    2. 如下錯誤:

Do you want to continue? [Y/n] Abort.

The command '/bin/sh -c apt-get install dnsmasq-base' returned a non-zero code: 1

    解決辦法:在dockerfile 中的 install 的時候,加上 -y  參數,表示 選擇yes。即 apt-get -y install xxx.deb 即可。


    3.  如何進入 已經啓動的容器:docker exec -it 容器id  /bin/bash


參考(建議全部看完):
  1. http://dockerpool.com/static/books/docker_practice/introduction/README.html



一些疑問:
在實際的部署中,遇到了一些困難,一個是設計上的,一個是具體部署細節上的。
設計上的:一般什麼東西會放在Docker 中,我理解是 微服務,就也就是具體的業務模塊代碼,這些其實都是無狀態的。那麼對於有狀態的,比如數據庫,我們是否需要還放在 Docker 中跑。這樣對於以後做數據庫的集羣或者分佈式是否方便。再比如說 nginx 是否 需要放在 Docker中,還是和Docker 平級?
具體部署上:寫dockerfile 文件的時候,你怎麼保證寫的這些命令不出錯,寫一條命令就 docker build 一次,然後再 run 進去看看ok不ok??還是說先run 進去,再安裝好東西,再 history 拿到執行過的所有命令,再寫到 dockerfile 中??

望賜教,3Q




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