開發也需了解的運維知識之Docker

  • 2020 年 2 月 19 日
  • 筆記

點擊上方「碼農沉思錄」,選擇「設為星標」

優質文章,及時送達

docker容器化部署應用可以簡化應用的部署流程。假設部署一個應用需要在機器上安裝和配置nginxtomcat,如果需要新增一台伺服器,或者切換伺服器,那麼就要重複同樣的操作,安裝nginxtomcat並配置。容器化部署就是一次配置到處使用,將安裝nginx配置nginx這一系列工作製作成一個鏡像,在伺服器上通過docker拉取鏡像並啟動容器即可,基於此實現集群自動伸縮。

docker入門簡單,用好難,特別是製作鏡像。隨便做一個鏡像就是1g大小,這該怎麼用。如果每次部署都要拉1g的鏡像,想想都可怕。如果在Dockerfile中使用yum安裝一些軟體,build的時間會很長,加上鏡像太大,傳輸也耗時。應盡量使用安裝包安裝替換yum安裝,以及使用盡量小的基礎鏡像。

使用Dockerfile構建鏡像,我們可以理解為,docker基於Dockerfile中的FROM基礎鏡像,啟動了一個容器,然後在容器中執行Dockerfile中定義的腳本,執行完成後再打包成鏡像。

docker的鏡像是分層的,你可以先訂製一個基礎鏡像,再通過基礎鏡像去實現差異化訂製。比如部署一個java項目,每台機制都需要jdk,但並不是每台機器都需要安裝nginx,那麼就可以先製作一個jdk基礎鏡像。當然,製作jdk基礎鏡像也是基於更底層的基礎鏡像,比如centos。然後再基於jdk基礎鏡像製作nginx鏡像,再製作應用鏡像。製作應用鏡像如果需要用到nginx就可以基於nginx鏡像,不需要依賴nginx的就可以直接基於jdk鏡像。

docker的命令不需要記,動動手去試一試就記住了,記不住可以使用docker -help查看命令。新版本docker將命令規範了,如docker image是鏡像相關的,docker container是容器相關的,同樣,也可以使用docker container -help來查看命令幫助。

Docker的埠、網路與容器卷

學習doker除了鏡像製作之外,還需要理解這三點:埠映射、網路模式、容器卷(volume)。

埠映射

將宿主機埠映射到容器的埠,外部通過訪問宿主機埠從而訪問容器內應用。如容器中redis使用的埠是6379,可以將宿主機的10880埠與容器的6379埠映射,外部通過宿主機ip10880埠訪問容器中的redis

### 使用鏡像運行容器  ### -p 10880:6379 將宿主機10880埠映射到容器6379埠  [root@wujiuye01 redis-app]# docker container run -itd --name simple-redis                    -p 10880:6379 wujiuye/simple-redis:5.0.7  05676da445839b1f4a1995148b4656d029721503a16d67edad37956fe7ea9f3a    ### 宿主機訪問容器中的redis  [root@wujiuye01 redis-app]# /root/redis/redis-5.0.5/src/redis-cli -p 10880  127.0.0.1:10880>

網路模式

docker支援5種網路模式,這裡不做詳細分析,因為我不是很了解。在啟動容器時,可以指定使用哪種網路模式:docker container run --network [網路模式]

  • bridge: 默認使用,docket啟動後默認創建一個docker0網橋,默認創建的容器也是添加到這個網橋中。
  • host: 容器不會獲得一個獨立的network namespace,而是與宿主機共用一個。

容器卷(volume)

應用部署在一台伺服器上運行會產生日記,不能隨著容器的刪除而導致日記被刪除,所以需要將容器中的工作目錄與宿主機的目錄映射。或者說mysql容器,容器移除而資料庫文件不能刪除。docker為我們提供了三種不同的方式將容器卷或宿主機目錄從宿主機掛載到容器中:volumebind mounttmpfs

volumes

docker管理宿主文件系統的一部分(/var/lib/docker/volumes/容器id)

  • 創建容器卷:docker volume create test-vol
  • 查看容器卷:docker volume inspect test-vol
  • 將容器卷掛載到容器的目錄:docker container run -itd --name test --mount src=test-vol,dst=/data/apps/test wujiuye/test:1.0.0

--mount src=test-vol,dst=/data/apps/test: 將容器卷掛載到容器的/data/apps/test目錄。

將文件放到容器的/data/apps/test目錄下,可以在宿主機的/var/lib/docker/volumes/test-vol目錄看到,反過來也是一樣的。如果不指定--mount,默認也是使用volumes,並且容器卷的名稱就是容器id,也是在/var/lib/docker/volume/目錄下。

### 創建容器卷  [root@wujiuye01 docker]# docker volume create test-vol  test-vol  ### 查看容器卷資訊  [root@wujiuye01 docker]# docker volume inspect test-vol  [      {          "CreatedAt": "2020-01-04T17:57:08+08:00",          "Driver": "local",          "Labels": {},          "Mountpoint": "/var/lib/docker/volumes/test-vol/_data",          "Name": "test-vol",          "Options": {},          "Scope": "local"      }  ]  ### 將容器卷掛載到容器  [root@wujiuye01 docker]# docker container run -itd --name test           --mount src=test-vol,dst=/data/apps/test wujiuye/test:1.0.0

bind mounts

可以存儲在宿主機系統的任意目錄,宿主機的目錄必須存在。如果宿主機新增磁碟是掛載在/data目錄的,建議使用這種。如使用awsec2實例。

docker container run -itd --name test --mount type=bind,src=宿主機目錄,dst=容器目錄 wujiuye/test:1.0.0

將指定的宿主機目錄掛載到容器的指定目錄。將文件放到<容器指定目錄>下,可以在<宿主機指定目錄>看到,反過來也是一樣的。

tmpfs

掛載存儲在宿主機系統的記憶體中,不會寫入宿主機的文件系統

Docker的安裝與啟動

docker安裝

# 較舊的 Docker 版本稱為 docker 或 docker-engine 。如果已安裝這些程式,請卸載它們以及相關的依賴項。  sudo yum remove docker                     docker-client                     docker-client-latest                     docker-common                     docker-latest                     docker-latest-logrotate                     docker-logrotate                     docker-engine    # 安裝所需的軟體包。yum-utils 提供了 yum-config-manager ,並且 device mapper 存儲驅動程式需要 device-mapper-persistent-data 和 lvm2  sudo yum install -y yum-utils     device-mapper-persistent-data     lvm2    # 設置穩定的倉庫。  sudo yum-config-manager       --add-repo       https://download.docker.com/linux/centos/docker-ce.repo    # 安裝最新版本的 Docker Engine-Community 和 containerd  sudo yum install docker-ce docker-ce-cli containerd.io

docker服務啟動與停止

## 停止  sudo systemctl stop docker  ## 啟動  sudo systemctl start docker

Docker使用簡單事例

製作一個簡單的redis鏡像

準備redis安裝包和配置文件,新建一個Dockerfile文件,目錄結構如下:

-rw-r--r-- 1 root root     583 Jan  4 18:56 Dockerfile  -rw-r--r-- 1 root root 1984203 Jan  4 18:52 redis-5.0.7.tar.gz  -rw-r--r-- 1 root root   61797 Jan  4 18:52 redis.conf

編寫Dockerfile文件,基於centos:7鏡像

FROM centos:7  MAINTAINER wujiuye <[email protected]>    # 使用ps 命令 :ps -ef|grep redis  RUN yum install -y procps    # redis安裝包和配置文件  ADD redis-5.0.7.tar.gz /usr/local/redis/  COPY redis.conf /usr/local/redis/local-redis.conf    # 安裝gcc  RUN yum install gcc -y  # 安裝make  RUN yum install make -y    # 編譯redis  RUN cd /usr/local/redis/redis-5.0.7 &&       make    RUN yum clean all    EXPOSE 6379    # 啟動redis  ENTRYPOINT /usr/local/redis/redis-5.0.7/src/redis-server  CMD ["/usr/local/redis/local-redis.conf"]
  • 1、COPYADD命令的src只能使用相對路徑,需要將文件拷貝到Dockerfile的同級目錄下
  • 2、不要將redis安裝包與redis配置文件COPYADD到容器的掛載目錄下,否則因宿主機的源目錄下沒有這些文件,容器啟動起來就找不到這些文件。構建鏡像時將文件放在容器的/data/apps/目錄下,而啟動容器時配置宿主機目錄掛載到容器的/data/apps/docker會將鏡像中原有的/data/apps/目錄移除,才可以掛載。
  • 3、RUM運行多條命令可使用&&符號連接,也可以寫多個RUN

構建鏡像

### 目錄下的文件  [root@wujiuye01 redis-app]# ls  Dockerfile  redis-5.0.7.tar.gz  redis.conf    ### 構建鏡像  [root@wujiuye01 redis-app]# docker image build --tag wujiuye/simple-redis:5.0.7 .  ....  Successfully built 2aab79854763  Successfully tagged wujiuye/simple-redis:5.0.7

--tag打標籤,最後的『.』Dockerfile文件所在的位置。

根據鏡像啟動容器

docker container run   --rm -itd   --ulimit nofile=102400:102400   --name=simple-redis   -p 10880:6379   # 可寫多個  --mount type=bind,src=/data/redis-app/,dst=/usr/local/redis   wujiuye/simple-redis:5.0.7
  • --rm: 如果容器存在則刪除,只是移除容器,正在運行的容器不會停止
  • --name=simple-redis: 給容器取一個名字
  • -itd: -i-t-d的結合
  • --ulimit nofile=102400:102400 設置ulimit
  • -p 10880:6379 宿主機與容器的埠映射
  • --mount type=bind,src=...,dst=... 文件系統為bind mountsrc為宿主機的目錄,dst為容器中的目錄

查看容器資訊

[root@wujiuye01 redis-app]# docker container ls  ### 容器id  使用的鏡像 容器執行的命令 創建時間   容器狀態  埠資訊  容器名稱  CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                     NAMES  05676da44583        wujiuye/simple-redis:5.0.7   "/bin/sh -c /usr/loc…"   6 minutes ago       Up 6 minutes        0.0.0.0:10880->6379/tcp   simple-redis

將鏡像push到docker hub

在測試完鏡像可用之後,可以選擇push到遠程倉庫,也可自己搭建一個鏡像倉庫。

  • 1)、註冊hub.docker.com帳號,id不要隨便填寫,如:wujiuye
  • 2)、創建一個倉庫,如:wujiuye/simple-redis
  • 3)、如果需要,將本地的鏡像打標籤,對應到遠程倉庫,如:docker tag local/test-redis:1.0.5 wujiuye/simple-redis:5.0.7。本地鏡像與遠程倉庫鏡像標籤不同時使用。
  • 4)、docker login 輸入用戶名密碼登陸
  • 5)、docker push wujiuye/simple-redis:5.0.7 推送鏡像至遠程倉庫
[root@wujiuye01 redis-app]# docker push wujiuye/simple-redis:5.0.7  The push refers to repository [docker.io/wujiuye/simple-redis]  dafbadcc43aa: Pushing [==>                                                ]  1.281MB/23.62MB  879a0e8874ba: Pushing [=============================>                     ]  66.96MB/111.8MB  ccc522a455bc: Pushing [>                                                  ]  549.9kB/100.2MB  879a0e8874ba: Pushing [================================>                  ]  73.04MB/111.8MB  ccc522a455bc: Pushing [>                                                  ]  1.107MB/100.2MB  ff7b8add839d: Pushing [=================>                                 ]  51.75MB/146.8MB  dca066a10cae: Pushing [>                                                  ]  557.1kB/100.8MB  77b174a6a187: Waiting

Other

容器停止

1)、docker kill [容器名]  可選參數:  --signal: 發送訊號量    2)、docker stop []

刪除容器和鏡像

  • 1)、刪除所有鏡像:docker rmi $(docker images -q)
  • 2)、刪除所有容器:
1)、先停止所有容器:docker stop $(docker ps -a -q)  2)、刪除所有容器:docker rm $(docker ps -a -q)

刪除某個鏡像:

1)、docker image rm [repository,如:wujiuye/simple-redis:5.0.7]  2)、docker image rm [鏡像id]

刪除某個容器:

docker container rm [容器名稱 或 容器id]

祝大家在2020年工作順路,家庭幸福,合家團圓