開發也需了解的運維知識之Docker
- 2020 年 2 月 19 日
- 筆記
點擊上方「碼農沉思錄」,選擇「設為星標」
優質文章,及時送達
docker
容器化部署應用可以簡化應用的部署流程。假設部署一個應用需要在機器上安裝和配置nginx
、tomcat
,如果需要新增一台伺服器,或者切換伺服器,那麼就要重複同樣的操作,安裝nginx
、tomcat
並配置。容器化部署就是一次配置到處使用,將安裝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
埠映射,外部通過宿主機ip
和10880
埠訪問容器中的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
為我們提供了三種不同的方式將容器卷或宿主機目錄從宿主機掛載到容器中:volume
、bind mount
、tmpfs
。
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
目錄的,建議使用這種。如使用aws
的ec2
實例。
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、
COPY
、ADD
命令的src
只能使用相對路徑,需要將文件拷貝到Dockerfile
的同級目錄下 - 2、不要將
redis
安裝包與redis
配置文件COPY
或ADD
到容器的掛載目錄下,否則因宿主機的源目錄下沒有這些文件,容器啟動起來就找不到這些文件。構建鏡像時將文件放在容器的/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 mount
,src
為宿主機的目錄,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年工作順路,家庭幸福,合家團圓