Docker從入門到入門

本文定位入門貼!


Docker簡述

以前做開發的小夥伴經常會遇到這樣的問題,在本地測試環境跑的代碼好好的,發到生產環境就是遇到了問題。各種排查千辛萬苦之後發現,是配置環境、軟件版本、操作系統的不同導致。這時候要麼換線上,要麼換線下。要是遇到開發小夥伴的個人電腦上開發環境版本不同,你是win,我是mac,他是linux的時候,更是抓狂。

Docker的誕生就是為了解決這種問題。沙箱機制的虛擬容器引擎跟傳統的虛擬化不同。傳統的虛擬機從底層硬件級別就開始進行模擬:硬件層面(cpu,顯卡,網卡,硬盤,內存,串口)->操作系統(win,linux,mac)->軟件(nginx,chrome)等等全方位的模擬,獨佔了內存,算力等等。docker是指單純的從軟件層面進行虛擬即可,底層有hostOS進行支撐,他自己只要docker的守護進行代替,上層建立不同的容器,不同的容器之間相互隔離。

官網舉例就很貼切,docker就是集裝箱。原來拉水果的船隻拉水果,放上化工品肯定出問題,你需要不同的船。而用了docker之後,大船上面可以放很多的集裝箱,你需要的東西在你自己的集裝箱裡面封好就可以了。而且這個集裝箱拉到其他船上也一樣的。

重要概念

Docker是自己是容器引擎,是一個裝容器大船。上面通過run命令跑起來的實例就是容器container。作為標準放在這裡的容器模板就是鏡像image,可以理解為一些靜態文件。而存放這些鏡像靜態文件,即為倉庫hub

容器和鏡像的關係可以理解為,聲明的對象和實例化以後的對象的關係。

常用命令

注意,docker命令默認只能root用戶執行,下面命令遇到dial unix /var/run/docker.sock: connect: permission denied權限不足的問題,命令前加sudo

<code>$ docker ps //查看當前運行的容器列表
$ docker ps -a //查看所有運行的容器列表
$ docker images //查看鏡像,包含來源、標籤、id、創建時間、大小
$ docker search [鏡像關鍵詞] //搜索已有鏡像
$ docker commit -m="描述信息" -a="鏡像作者" [容器 ID] [創建的鏡像名] //更新鏡像
$ docker stop [容器ID] //停止容器

$ docker start [容器ID] //啟動曾經啟動過的容器列表
$ docker rm [容器ID] //刪除容器,可多個
$ docker rmi [鏡像ID] //刪除鏡像,可多個
$ docker inspect [容器ID] | grep IPAddress //查看容器IP地址

//進入一個正在運行的容器
$ docker exec -it 775c7c9ee1e1 /bin/bash

/<code>

docker run 啟動容器參數詳解

<code>-d //啟動後直接進入後臺,並返回容器ID
-i //以交互模式運行容器,通常與 -t 同時使用
-t //為容器重新分配一個偽輸入終端,通常與 -i 同時使用
-P //隨機端口映射,容器內部端口隨機映射到主機的高端口
-p //指定端口映射,格式為: -p 8080:80 宿主端口:容器端口
--name="nginx-lb" //為容器指定一個名稱。
--volume , -v\t//文件/文件夾映射,格式為: -v /a:/a 宿主文件:容器文件
--link=[] //添加鏈接到另一個容器

最後加上你要選擇的鏡像名稱

/<code>

Docker的安裝由於不同操作系統之間的安裝差別挺大,自行找官網對應版本的安裝教程。不過下面docker三劍客的第一個就要當場了,就是為了簡化docker安裝過程,快速虛擬出新的docker主機。

Dockerfile構建鏡像

我們通過 docker build 命令從0構建一個鏡像,為此我們需要創建一個Dockerfile文件來告訴docker一步一步來如何做。

常用語法說明

<code>FROM    centos:6.7      //指定從哪個鏡像開始
MAINTAINER Fisher "[email protected]" // 維護人員信息作者和郵箱

ARG user # ARG user=root //構建鏡像時指定參數
RUN /bin/echo 'root:123456' |chpasswd // 執行命令,直接運行具體命令即可
EXPOSE 22 //開啟端口
WORKDIR /data //為RUN、CMD、ENTRYPOINT以及COPY和AND設置工作目錄
ENV NGINX_HOST=tingno.com //設置環境變量
COPY ./start.sh /start.sh //複製文件或目錄
VOLUME ["/var/lib/mysql"] //指定容器掛載點到宿主機自動生成的目錄或其他容器
ADD index.html /var/www/html/index.html //複製文件
CMD /usr/sbin/sshd -D //當啟動容器時執行的腳本文件
/<code>

最最簡單的案例 直接用vue的腳手架,新建一個項目,在項目文件夾下面加入dockerfile文件。這是Dockerfile的文件內容。

<code>FROM hub.c.163.com/library/nginx:latest
MAINTAINER Tingno "[email protected]"
ADD ./dist /usr/share/nginx/html


WORKDIR /usr/share/nginx/html
RUN echo '這是一個本地構建的nginx鏡像' > a.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
/<code>

然後執行 docker build -t demo2 . 結果如下:

<code>docker@vue:/data/dockerdemo$ docker build -t demo3 .
Sending build context to Docker daemon 614.9kB
Step 1/7 : FROM hub.c.163.com/library/nginx:latest
---> 46102226f2fd
Step 2/7 : MAINTAINER Tingno "[email protected]"
---> Using cache
---> c6455e731908
Step 3/7 : ADD ./dist /usr/share/nginx/html
---> Using cache
---> 86f6089a6b83
Step 4/7 : WORKDIR /usr/share/nginx/html
---> Using cache
---> daa21c35ad15
Step 5/7 : RUN echo '這是一個本地構建的nginx鏡像' > a.html
---> Running in 862ea41d2033
Removing intermediate container 862ea41d2033
---> 1775e0d786eb
Step 6/7 : EXPOSE 80
---> Running in 329ce829d6d9
Removing intermediate container 329ce829d6d9
---> c74d77449798
Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
---> Running in 936f82eb6306
Removing intermediate container 936f82eb6306
---> cc6cbe04ada6
Successfully built cc6cbe04ada6
Successfully tagged demo3:latest
/<code>

裡面每一步,都會生成一個新的中間鏡像,docker images -a 一大堆。 另外,這裡就是講所有當前文件夾內容都發送給引擎去進行生成鏡像,但是很多文件都不需要,這裡就用到了.dockerignore文件,他的作用和.gitignore文件一樣的,基本上通常屏蔽的內容都一樣,只是代碼文件和生成項目文件反過來就是了。

這時候再來運行啟動容器命令,就可以通過你的本機來進行訪問了。

<code>docker run -d -p 8083:80 demo3
/<code>

如果發現你生成的鏡像啟動就死掉了,而其他的官方鏡像都可以的話,說明你的構建命令有問題,自行排查構建文件。

前端迭代發佈流程

學習到這裡,我們做前端的小夥伴基本上就差不多了,畢竟平時開發就是單純的把代碼git push完發上去。 後續的自動化部署的內容,其實就是對應的引擎自動去git代碼倉庫裡面pull最新的代碼,然後自動npm run build前端打包, 然後docker build成鏡像文件,關掉老的容器,用新的鏡像文件啟動新的容器。項目就算迭代發佈成功了,這其中最最重要的就是dockerfile文件了。

這時候問題來了,一般稍微大點兒的項目,不可能只有一個前端服務,還有可能有後端接口,數據庫,網關,消息隊列等等,這些都需要一個鏡像一個鏡像的打包、啟動。分享一個項目給其他人的時候要完整搭建這些,就有了docker三劍客之一compose

Docker Componse

先來看定義: Compose 是用於定義和運行多容器 Docker 應用程序的工具。通過 Compose,您可以使用 YML 文件來配置應用程序需要的所有服務。然後,使用一個命令,就可以從 YML 文件配置中創建並啟動所有服務。

docker-compose命令想要使用的話,需要安裝,安裝命令如下,裡面版本號自行更換,而且這是國內安裝鏈接,你懂的

<code>$ sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
/<code>

YML文件就是告訴docker引擎,我要啟動好幾個容器,都要做啥做啥做啥。這裡也有yaml文件的入門鏈接 yaml入門教程, 幫助理解的話,就是json的另一種寫法。

配置參數說明

<code>version:3
services: //需要啟動的服務列表
services.[name] //具體的服務名稱,這裡發服務可以自定義
services.[name].build //指定為構建鏡像Dockerfile
services.[name].depends_on //設置依賴關係,這裡面的服務啟動了,當前服務才可以啟動。
services.[name].images //指定容器運行的鏡像
services.[name].deploy //有關服務部署的內容,只有在swarm模式下才有用。
services.[name].entrypoint //覆蓋容器默認的 entrypoint。

services.[name].expose //暴露端口,但不映射到宿主機,只被連接的服務訪問。僅可以指定內部端口為參數:
services.[name].volumes //將主機的數據卷或著文件掛載到容器裡。
services.[name].networks //配置容器鏈接的網絡
services.[name].secrets //敏感數據

networks:[name] //當前部署要用到的網絡具體配置
secrets:[name] //當前部署要用到的敏感數據的具體配置
volumes:[name] //當前部署要用到的數據卷的具體配置
/<code>

簡單舉例 我們把上面Dockerfile文件拆解下來到compose文件裡面就是如下

<code>version: '3'
services:
web:
container_name: web
image: hub.c.163.com/library/nginx
ports:
- "8080:80"
volumes:
- ../dockerdemo/dist:/usr/share/nginx/html
expose:
- "80"
/<code>

然後啟動一下對應的yml文件

<code>$ docker-compose -f demo.yml up -d
/<code>

也是相當於啟動了一個鏡像服務,其他更多的配置就可以去參照比較複雜的,這裡推一個配置 lnmp環境的容器編排項目。鏈接

到這裡,我們開始從最開始的docker命令啟動容器 —> 使用Dockerfile一鍵啟動完整容器 -> 使用docker-compose一鍵啟動好幾個容器。

如果你的項目就一臺主機,恭喜,到這裡就完全夠你用了。再後面我們要說的是docker三劍客成員docker-swarm,將上面的鏈條進一步延長,我們可以同時在好多機器上,啟動好多容器。但是前提,我們要很方便的造出來很多主機,這裡就是Docker三劍客 Docker Machine,目的就是很方便的造很多主機。

Docker Machine

Docker Machine 是一種可以讓您在虛擬主機上安裝 Docker 的工具,並可以使用 docker-machine 命令來管理主機。

docker是用來管理船上的集裝箱,Docker-Machine用來管理大船的。使用 docker-machine 命令,您可以啟動,檢查,停止和重新啟動託管主機,也可以升級 Docker 客戶端和守護程序,以及配置 Docker 客戶端與您的主機進行通信。安裝 Docker Machine 之前你需要先安裝 Docker。

常用命令

<code>$ docker-machine ls  //列出現在可用的機器,包含主機名稱,狀態,驅動類型,ip,docker版本,錯誤信息等等
$ docker-machine create --driver [驅動類型] [主機名稱] //新建主機,驅動類型可為virtualbox 或者其他

$ docker-machine ip [主機名稱] //看看主機的IP
$ docker-machine stop [主機名稱] //停止機器
$ docker-machine start [主機名稱] //啟動機器
$ docker-machine ssh [主機名稱] //進入機器
/<code>

這裡偷偷來一條掛載virtualbox共享文件夾的機器內命令 sudo mount -t vboxsf share /data

這時候,最起碼造3臺docker主機來,下面我們就要在這寫主機上來用做容器編排了。

偷偷來一個一把可以創建好多主機的命令,只要你的內存夠。

$ for NODE in `seq 1 5`; do docker-machine create --driver virtualbox "node-${NODE}"; done

Swarm集群管理

Docker Swarm是Docker的集群管理工具,將Docker本身從主機這個單元抽象出來,轉變成虛擬的Docker主機,你不再需要關注某個docker容器運行在具體的哪臺Docker主機上了,統一都是有Swarm管理單元來進行管理。相應的Swarm就分為了管理節點master,和工作節點worker。而對應的命令,就是先任命老大,幹活的找到老大,老大派活兒,後面比較好的,大家一起幹活。

理論上老大能一起幹活,但是在生產環境裡,不建議這麼做,而且我們還會任命副的老大用來接替萬一掛了的老大。

對應如下整個項目內容查看的一些操作命令:

  • 第一波是本身swarm的管理,相當於公司頂層設計。
<code>$ docker swarm init --advertise-addr [IP] //創建一個新公司
$ docker swarm join //加入新公司
$ docker swarm join-token //管理加入公司的邀請碼
$ docker swarm update //調整位置
$ docker swarm leave //離開公司
/<code>
  • 第二波是node節點管理,公司的幹活的人頭管理
<code>$ docker node ls //查看集群中都有哪些節點
$ docker node promote [節點名稱/ID] //提升某個節點為管理節點
$ docker node demote [節點名稱/ID] //降級某個節點為幹活節點
$ docker node inspect [節點名稱/ID] --pretty //查看節點信息
/<code>
  • 第三波是公司要開始做項目了,進行項目管理
<code>$ docker stack deploy [項目名稱] --compose-file=[配置文件地址].yml   //項目部署
$ docker stack ls //查看項目列表
$ docker stack services [項目名稱] //查看項目的任務列表
$ docker stack ps [服務名稱] //列出整個項目裡面節點上的任務,包括沒有運行的

$ docker stack rm [服務名稱] //移除一個或者多個項目
/<code>
  • 第四波是具體項目裡面的任務管理
<code>$ docker service ls //查看集群中運行發服務
$ docker service ps [服務名稱] //查看具體的服務
$ docker service inspect --pretty [服務名稱/ID]
$ docker service create --name [服務名稱] --replicas [分配節點數量] -p 80:80 [鏡像名稱] //新增一個服務
$ docker service rm [服務名稱] //刪除服務
$ docker service scale [服務名稱/ID]=[調整後的數量] //調整服務節點數量
/<code>

對於Swarm整個公司來說,集群上的每臺docker主機都是一個node節點一個幹活的人,發佈總的項目是堆stack, 發佈下去的總項目裡面的任務服務service,每個節點被攤牌到具體的任務就是tasks。所以每個人手上做的具體的活兒就是tasks,tasks是最小的單元,對應每個docker機器上的容器container。

在前面的前端項目裡面來一個簡單的compose.yml文件,配置如下

<code>version: '3'
services:
web:
image: hub.c.163.com/library/nginx:latest
ports:
- "8080:80"
networks:

- frontend
volumes:
- "./dist:/usr/share/nginx/html"
deploy:
replicas: 3
networks:
frontend:
/<code>

下面是具體流程如下:

<code>//第一步:任命老大。就是在master機器上進行swarm初始化,下面會生成一條認老大的命令,記得複製好
$ docker swarm init --advertise-addr 192.168.99.100

//第二步:認老大。在所有worker機器上執行老大給的命令,裡面有說老大是誰,還有暗號。
$ docker swarm join --token SWMTKN-1-37ruaep41ju82rxt6zus7c83xuyszzowethoncv8itekso0vu8-ab7vksim9wk40xapu5mlwxwew 192.168.99.100:2377

//第三步:老大派活兒。創建服務
$ docker stack deploy demo --compose-file=compose.yml

//第四步:大家幹活。任務執行
$ docker stack ls
/<code>

這時候,使用瀏覽器具體訪問下你啟動的IP,看到你自己的內容,就算ok了。

文末

整個從前到後把docker的內容梳理完之後,就是不斷的簡化過程。 為了抹平不同環境之間的差別,有了docker。 為了方便打包鏡像,有了Dockerfile。 為了在一臺機器上生成項目用給鏡像,有了docker-compose。 為了在好多臺機器上部署項目,有了docker-swarm。 為了快速創建docker主機,有了docker-machine。

另外,容器編排技術swarm的對手k8s現在風頭更勝,兩者的區別就像是記事本和編輯器的區別。都可以用,不過k8s更加複雜,你需要學習更多的內容,可以實現更多的可能。

如標題,本文為入門,主要幫助理解。歡迎各路大神拍磚撒花點贊轉發。


分享到:


相關文章: