Docker入門
[toc]
1. Docker架構
1.1 Docker鏡像與Docker容器的關系
父與子的關系,用Docker鏡像來創建Docker窗口;也類似于面向對象中類(鏡像)與對象(容器)的關系。
Docker | 面向對象 |
---|---|
容器 | 對象 |
鏡像 | 類 |
名字 | 解釋 |
---|---|
Docker鏡像(Images) | Docker鏡像是用于創建Docker容器的模板 |
Docker容器(Container) | 容器是獨立運行的一個或一組應用。 |
Docker客戶端(Client) | Docker客戶端通過命令行或者其他工具使用Docker API與Docker守護進程通信。 |
Docker主機(Host) | 一個物理或者虛擬的機器用于執行Docker守護進程和容器。 |
Docker倉庫(Registry) | Docker倉庫用來保存鏡像,可以理解為代碼控制中的代碼倉庫。Docker Hub提供了龐大的鏡像集合供使用。 |
Docker Machine | Docker Machine是一個簡化Docker安裝的命令行工具,通過一個簡單的命令行即可在相應的平臺上安裝Docker,比如VirtualBox、Digital Ocean、Microsoft Azure |
1.2 Docker改變了什么?
- 面向產品:產品交付
- 面向開發:簡化環境配置
- 面向測試:多版本測試
- 面向運維:環境一致性
- 面向架構:自動化擴容(微服務)
2. 安裝Docker
安裝Docker請查另一篇博客:http://www.lxweimin.com/p/87e7f6ada205
啟動docker
$ sudo systemctl start docker
3. Docker鏡像
3.1 Docker拉取鏡像加速
需要先登錄DaoCloud網站http://www.daocloud.io/mirror,
點擊立即使用,然后登錄,然后選擇你的系統:
Linux執行如下命令。
[root@linux-host2 ~]# curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://4a1df5ef.m.daocloud.io
docker version >= 1.12
{"registry-mirrors": ["http://4a1df5ef.m.daocloud.io"]}
Success.
這條命令實際上是在/etc/docker/daemon.json
文件中加一行配置:
{"registry-mirrors": ["http://4a1df5ef.m.daocloud.io"]}
3.2 鏡像相關的命令
docker search <鏡像名關鍵字> # 搜索鏡像
docker pull <鏡像名稱> # 拉取鏡像
docker images # 列出本地鏡像
docker rmi <鏡像名稱> # 刪除鏡像
3.3 導出/導入鏡像
# 先查看已有的鏡像
[root@linux-host2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hub.c.163.com/public/centos 7.2 2ce04a284fa8 21 months ago 288 MB
docker.io/training/webapp latest 6fae60ef3446 2 years ago 349 MB
# 導出鏡像
# docker save hub.c.163.com/public/centos:7.2 > centos-7.2.tar.gz
# 導入鏡像
# docker load < /root/centos-7.2.tar.gz
4. Docker應用
使用docker run
命令來在容器內運行一個應用程序,輸出Hello World
[root@openstack-control2 ~]# docker run ubuntu:15.10 /bin/echo "Hello world"
參數解析:
-
run
:運行一個容器; -
ubuntu:15.10
:指定要運行的鏡像,Docker首先從本地主機上查找鏡像是否存在,如果不存在,Docker就會從鏡像倉庫Docker Hub下載公共鏡像; -
/bin/echo "Hello World"
:在啟動的容器里執行的命令。
以上命令完整的意思可以解釋為:Docker 以 ubuntu15.10 鏡像創建一個新容器,然后在容器里執行 bin/echo "Hello world",然后輸出結果。
4.1 運行容器
4.1.1 運行交互式的容器
[root@openstack-control2 docker]# docker run -i -t ubuntu:15.10 /bin/bash
參數解析:
-
-i
:允許你對容器的標準輸入(STDIN)進行交互; -
-t
:在新容器內指定一個偽終端或終端。
4.1.2 啟動容器(后臺模式)
[root@openstack-control2 docker]# docker run -d ubuntu:15.10 /bin/sh -c "while true;do echo hello-world;sleep 1;done"
02c285ff03bbf167796be5e1b4ce7b2a835d8d795e68b4375e1ec61b892ed42b
參數解析:
-
-d
:后臺模式運行docker容器; - 還可以用
--name xxx
指定容器名稱叫xxx。 - 還可以用
--rm
,當容器停止運行后自動刪除,一般用在測試時。 -
--restart always
: 如果加上此選項,表示這個容器會在docker進程啟動后,立即自己啟動。
那一長串字符串是容器ID,對每個容器來說是唯一的;
4.2 --entrypoint的作用
有些容器啟動后會直接在前臺運行命令,導致你進入容器后不能做其他的事情。這時你可以使用run命令下的參數--entrypoint
,它的作用是覆蓋鏡像的默認入口點,示例如下:
啟動一個以python3.6為基礎鏡像的容器:
[root@docker ~]# docker run -it --name python3.6 python:3.6
Python 3.6.5 (default, Mar 31 2018, 01:15:58)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>>
容器啟動后,直接進入python的交互終端了,不能做其它操作,而exit后,就直接退出容器了。這里加入
--entrypoint bash
參數,用bash覆蓋它默認的入口點。
[root@docker ~]# docker run -it --entrypoint /bin/bash --name python3.6 python:3.6
root@430e3c9c09ac:/#
root@430e3c9c09ac:/#
這樣進入容器后,就是bash交互了。
4.3 列出容器
列出正在運行的容器
[root@openstack-control2 docker]# docker ps
注意:默認只顯示正在運行的容器,加
-a(或 --all)
參數,可以顯示出所有容器。
**-l
**:查詢最后一次創建的容器
列出所有容器
[root@openstack-control2 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02c285ff03bb ubuntu:15.10 "/bin/sh -c 'while..." 12 minutes ago Exited (137) 11 minutes ago practical_hopper
7f1ee35531a8 ubuntu:15.10 "/bin/bash" 19 minutes ago Exited (0) 18 minutes ago upbeat_wiles
解釋:
- CONTAINER ID:容器ID,可以通過容器ID來操作此容器,也可以用容器名稱;
- IMAGE:此容器是由哪個鏡像創建的;
- COMMAND:容器中運行的命令;
- CREATED:創建時間;
-
STATUS:容器狀態,
Exited
表示退出; - NAMES:是啟動容器時,隨機為容器分配的一個名稱,也可以用來操作容器。
查看所有容器的ID
$ docker ps -a -q # 這條命令會將所有容器的ID顯示(只顯示容器ID)
4.4 查看容器內的標準輸出
[root@openstack-control2 docker]# docker logs 2b1b7a428627
可以用容器ID或容器名稱(用
docker ps
查看)
4.5 停止容器
[root@openstack-control2 docker]# docker stop 7f1ee35531a8
4.6 殺死正在運行的容器
[root@linux-host2 ~]# docker kill 000ed90ec053
4.7 查看容器對硬件資源的占用情況
[root@openstack-control2 docker]# docker stats 7f1ee35531a8
如果不指定容器ID或名稱,則默認顯示所有正在運行的容器的資源占用情況;加
-a(或--all)
,則顯示所有的容器;
4.8 查看容器的進程
[root@linux-host2 ~]# docker top adoring_noether
UID PID PPID C STIME TTY TIME CMD
root 9127 9115 0 00:05 ? 00:00:00 python app.p
4.9 查看容器的配置和狀態信息
[root@linux-host2 ~]# docker inspect adoring_noether
[
{
"Id": "251a6cacd10d5117025bda929ec1fb12f18b49cd2596c54d626c0c0e99491f48",
"Created": "2018-04-13T16:05:01.028216802Z",
"Path": "python",
"Args": [
"app.py"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 9127,
"ExitCode": 0,
"Error": "",
"StartedAt": "2018-04-13T16:05:01.186294688Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
省略...
可以通過--format
參數查看容器的指定參數
# 查看容器的狀態
[root@linux-host2 ~]# docker inspect --format '{{.State.Status}}' mycentos-2
running
# 查看容器的PID
[root@linux-host2 ~]# docker inspect --format '{{.State.Pid}}' mycentos-2
36897
4.10 進入容器
方式一:
# docker attach mycentos-2 # 進入名為mycentos-2的容器
這種方式進入容器容易卡死,而且
exit
退出后,容器也隨即停止,如果想讓容器在后臺運行,可以用快捷鍵Ctrl+p+q
。
方式二:
# docker exec -it 容器ID /bin/bash
直接
exit
退出容器而不會中斷容器運行。
方式三:
先獲取容器的PID
[root@linux-host2 ~]# docker inspect --format '{{.State.Pid}}' mycentos-2
36897
然后利用nsenter
命令進入到容器中
[root@linux-host2 ~]# nsenter -t 36897 -u -i -n -p
[root@000ed90ec053 ~]#
這樣即使退出容器了,容器也不會停止運行。
nsenter
命令可以進入到指定PID進程的名稱空間。如果系統沒有nsenter
命令,則需要安裝yum install util-linux
。
寫成腳本,更方便:
[root@linux-host2 ~]# cat in_container.sh
#!/bin/bash
CID=$1
PID=$(docker inspect --format "{{.State.Pid}}" $CID)
nsenter -t $PID -u -i -n -p
調用:
# ./in_container.sh mycentos-2
4.11 查看WEB應用程序日志
[root@linux-host2 ~]# docker logs -f 251a6cacd10
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.10.1 - - [13/Apr/2018 16:05:10] "GET / HTTP/1.1" 200 -
192.168.10.1 - - [13/Apr/2018 16:07:45] "GET / HTTP/1.1" 200 -
-f
:讓容器中運行的web日志像使用tail -f
一樣來輸出容器內部的標準輸出。
4.12 移除容器
# 需要先停止容器
[root@linux-host2 ~]# docker stop adoring_noether
# 然后再刪除指定的容器
[root@linux-host2 ~]# docker rm adoring_noether
4.13 導出容器
[root@linux-host6 ~]# docker export -o mytomcat.tar mytomcat
mytomcat.tar
是將容器導出后保存為mytomcat.tar文件名;mytomcat
是容器名稱,這里也可以寫容器ID。
4.14 docker run --privileged 選項的作用
使用該參數,container內的root擁有真正的root權限。
參考:https://blog.csdn.net/halcyonbaby/article/details/43499409
5. 端口映射
5.1 用-P
隨機端口映射
# 拉取鏡像
[root@openstack-control2 docker]# docker pull training/webapp
# 運行容器
[root@openstack-control2 docker]# docker run -d -P training/webapp python app.py
80f795a76ac1ef52b8f3a47cca2ae670cdbcd6fc42d01e702fbdbd53d6a41f51
-d
:讓容器在后臺運行;
-P
:將容器內部使用的端口映射宿主機上一個隨機端口。
通過docker ps
查看正在運行的容器:
多了端口信息:
PORTS
0.0.0.0:32768->5000/tcp
左邊是宿主機端口,右邊是容器內開啟的端口;就是做了一個端口映射;
5.2 用-p
來指定端口映射
[root@linux-host2 ~]# docker run -d -p 8000:5000 training/webapp python app.py
5959c85fae98e363cf2d339847fd3039f0de4b107fed2b362e905f74f176e55a
[root@linux-host2 ~]#
[root@linux-host2 ~]#
[root@linux-host2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5959c85fae98 training/webapp "python app.py" 5 seconds ago Up 4 seconds 0.0.0.0:8000->5000/tcp pensive_payne
指定IP:PORT映射
[root@linux-host2 ~]# docker run -d --name myweb -p 192.168.10.202:8000:5000 training/webapp python app.py
bf73ccb767a52a1f14a2c11a913a0d7d77263edc612380514e3ec0de489bb46f
PORTS
192.168.10.202:8000->5000/tcp
5.3 查看容器端口的映射情況
[root@linux-host2 ~]# docker port 251a6cacd10d
5000/tcp -> 0.0.0.0:8000
6. Docker數據管理
6.1 數據卷
將宿主機下的某個目錄掛載至指定的容器目錄。
如果不指定將哪個宿主機目錄掛載至容器目錄,則默認會將/var/lib/docker/vloumes/容器ID/_data
掛載至容器。
# docker run -it --name centos7.2 -v /data public/centos:7.2 /bin/bash
直接使用-v /data
會將宿主機的某個目錄掛載至容器的/data目錄。
這個目錄可以通過下面這條命令查看到;
[root@linux-host2 ~]# docker inspect --format "{{(index .Mounts 0).Source}}" centos7.2
/var/lib/docker/volumes/2a97b4ef3be22d590edf90089ee9fb32cf5a5848faa15076fff8f522bcbf406d/_data
指定宿主機目錄掛載至容器
# docker run -it --name test1 -v /opt/data/:/data:ro public/centos:7.2 /bin/bash
-v src:dst:ro
, src 是主機目錄,dst是容器目錄,ro是只讀權限。
6.2 數據卷容器
數據卷容器就是專門啟動一個容器掛載一個目錄,以后其他的容器直接從數據卷容器來掛載目錄,即使數據卷容器停止了,也不影響這些容器訪問掛載的目錄。使用--volumes-from
# 先啟動一個容器test1用來提供數卷
$ docker run -it --rm --name test1 -v /data public/centos:7.2 /bin/bash
# 再啟動一個容器test2,從test1容器掛載/data目錄至test2的/data目錄。
$ docker run -it --name test2 --volumes-from test1 public/centos:7.2 /bin/bash
7. 手動構建一個鏡像
我們以構建一個Nginx容器為例。
7.1 先拉取一個基礎鏡像
$ docker pull centos
7.2 利用基礎鏡像啟動一個容器
$ docker run -it --name mynginx public/centos /bin/bash
7.3 在容器內安裝nginx,并修改配置為使nginx為前臺運行
$ yum -y install nginx
$ echo "daemon off;" >> /etc/nginx/nginx.conf
7.4 提交鏡像
$ docker commit -m "My nginx" mynginx oldboyedu/mynginx:v1
commit
提交鏡像至本地倉庫,用docker images
查看鏡像是否生成。
- 命令格式:
docker commit -m "描述信息" CID new_image
CID
:是將要以哪個容器生成新的鏡像的容器ID或名稱;
new_image
:是新鏡像的名稱及版本,(鏡像名稱與版本號用冒號:
分隔。)
7.5 生成新容器
$ docker run -d --name nginx -p 81:80 -v /wwwroot:/data oldboyedu/mynginx:v1 nginx
最后跟著的nginx是nginx啟動命令。
8. Dockerfile構建鏡像
Dockerfile需要包含以下信息:
- 基礎鏡像信息
- 維護者信息
- 鏡像操作指令
- 容器啟動時執行的命令
8.1 Dockerfile中的關鍵字指令
Dockerfile通常包含以下關鍵字指令:
-
FROM
:它的媽媽是誰(基礎鏡像) -
MAINTAINER
:告訴別人,你創造了它(維護者信息) -
RUN
:你想讓它干啥(把shell命令前面加上RUN) -
ADD
:往它肚子里放點文件(copy文件,會自動解壓) -
WORKDIR
:我是cd,今天化了妝(當前工作目錄) -
VOLUME
:給我一個存放行李的地方(目錄掛載) -
EXPOSE
:我要打開哪扇門(開啟的端口) -
CMD
:最后啟動容器要執行的命令,如:CMD ["apachetcl -D FOREGROUND"]
8.2 Dockerfile示例
一個構建Nginx容器的Dockerfile示例:
[root@linux-host2 data]# vim Dockerfile
# This Dockerfile is build nginx container
# 基礎鏡像
FROM public/centos:7.2
# 維護者
MAINTAINER caigy caigy@163.com
# 執行的操作
RUN curl http://mirrors.aliyun.com/repo/epel-7.repo -o /etc/yum.repos.d/epel.repo
RUN yum install -y nginx
# 添加文件至容器中
ADD index.html /usr/share/nginx/html/index.html
# 修改nginx配置文件
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
# 開啟端口
EXPOSE 80
# 啟動容器時要執行的命令
CMD ["nginx"]
開始構建:
$ docker build -t caigy/nginx:1.0 /opt/data/
注意:基于Dockerfile構建鏡像時,需要指定Dockerfile父目錄(上述命令中的/opt/data/),或者用
.
指代當前目錄,表示Dockerfile就在當前目錄下。
-t
:為鏡像打一個標簽。
以下是構建過程中的輸出:
Sending build context to Docker daemon 6.144 kB
Step 1/8 : FROM public/centos:7.2
---> 2ce04a284fa8
Step 2/8 : MAINTAINER caigy caigy@163.com
---> Using cache
---> b7e06003d244
Step 3/8 : RUN curl http://mirrors.aliyun.com/repo/epel-7.repo -o /etc/yum.repos.d/epel.repo
---> Running in 31b2f1dafe05
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1084 100 1084 0 0 14137 0 --:--:-- --:--:-- --:--:-- 14263
---> c4b667b90187
Removing intermediate container 31b2f1dafe05
Step 4/8 : RUN yum install -y nginx
---> Running in 10ec5f05491e
省略部分輸出......
Step 7/8 : EXPOSE 80
---> Running in 027863d66b45
---> 8cc1cdc2c890
Removing intermediate container 027863d66b45
Step 8/8 : CMD nginx
---> Running in 9d62c62bd97c
---> 2f8bea7e3937
Removing intermediate container 9d62c62bd97c
Successfully built 2f8bea7e3937
查看本地鏡像是否有剛才構建的鏡像:
[root@linux-host2 data]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
caigy/nginx 1.0 2f8bea7e3937 7 minutes ago 477 MB
8.3 啟動容器
利用剛剛構建的鏡像啟動一個容器:
[root@linux-host2 data]# docker run -d --name mynginx -p 8800:80 caigy/nginx:1.0 nginx
e799d2abe242657477d356378981c801d0c5b49115a7b82965148d082fdbb74f
查看容器:
[root@linux-host2 data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e799d2abe242 caigy/nginx:1.0 "nginx" 4 seconds ago Up 4 seconds 22/tcp, 0.0.0.0:8800->80/tcp mynginx
假設宿主機ip是:x.x.x.x,那么瀏覽器輸入:http://x.x.x.x:8800驗證容器是否啟動成功。
9. CentOS 7.x 下Docker橋接網絡配置
docker默認提供了一個隔離的內網環境,啟動時會建立一個docker0的虛擬網卡,每個容器都是連接到docker0網卡上的。而docker0的ip段為172.17.0.1,如果想讓容器與宿主機同一網段的其他機器之間相互訪問,就必須在啟動docker的時候將某個端口映射到宿主機的端口。如果這樣,大家會發現很麻煩,而且在企業里面也沒這么使用的,比較弱。
大家應該知道KVM的橋接網絡非常方便,其實docker也比較方便,只是不是docker自帶的橋接而已,接下來講解centos7下如何快速實現docker容器橋接網絡,并為容器分配外網IP。
物理機的IP:192.168.1.7 網關:192.168.1.1
停止docker服務;
systemctl stop docker
新建橋接網卡br0;
brctl addbr br0
ip link set dev br0 up
為br0分配物理網絡中的IP地址;
這里可直接用宿主機的IP,接下來會清空宿主機的IP。
ip addr add 192.168.1.7/24 dev br0
將宿主機網卡的IP清空,并將宿主機網卡掛至br0上;
ip addr del 192.168.1.7/24 dev eth0
brctl addif br0 eth0
# 將宿主機eth0網卡掛到br0上刪除原路由,并為br0設置路由
ip route del default
ip route add default via 192.168.1.1 dev br0
-
設置docker服務啟動參數
vim /etc/sysconfig/docker-network
,其他系統可能在/etc/sysconfig/docker
下。
改成如下行即可:DOCKER_NETWORK_OPTIONS="-b=br0"
啟動docker服務
systemctl docker start
-
刪除docker0網卡
$ ip link set dev docker0 down #先關閉docker0網卡 $ brctl delbr docker0 #再刪除
安裝pipework
git clone https://github.com/jpetazzo/pipework
cp ./pipework/pipework /usr/local/bin/
啟動容器并設置網絡
docker run -itd --net=none --name=mycentos cgy/mycentos:v1 /bin/bash
為mycentos容器設置一個與橋接物理網絡同地址段的
ip/掩碼@網關
pipework br0 mycentos 192.168.1.10/24@192.168.1.1
-
進入容器查看IP
docker exec -it mycentos /bin/bash
如下圖:
image.png
以上2~5步通過命令行新建的橋接網卡br0,在服務器重啟后就會失效,要想永久生效,就需要創建網卡配置文件了。如下 :
- 新建br0的網卡配置文件;
vim /etc/sysconfig/network-scripts/ifcfg-br0
TYPE=Bridge
DEVICE=br0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.1.7
GATEWAY=192.168.1.1
PREFIX=24
NM_CONTROLLED=no
DNS1=8.8.8.8
- 修改eth0網卡配置文件:
vim /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE="Ethernet"
BOOTPROTO="static"
NAME="eth0"
UUID="5c013315-95d6-4f08-a61d-1b8340a9cb94"
DEVICE="eth0"
ONBOOT="yes"
BRIDGE=br0 # 表示橋接至br0網卡上
- 重啟網卡
systemctl restart network
10. Docker磁盤熱擴容
默認情況下,docker容器的空間是10G。在實際生產環境下,對docker容器進行熱擴容(動態擴容)是非常重要的一個需求。
Docker容器動態擴展的優點:
1)不需要修改docker配置,不需要重啟docker服務;
2)可以直接對運行中的容器進行動態擴展(只能增,無法縮);
Docker容器動態擴展的條件:
1)docker存儲引擎必須是devicemapper
。可通過docker info
查看:Storage Driver: devicemapper
10.1 操作環境
宿主機系統版本:
[root@linux-host2 ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
Docker版本:
[root@linux-host2 ~]# docker version
Client:
Version: 18.04.0-ce
API version: 1.37
Go version: go1.9.4
Git commit: 3d479c0
Built: Tue Apr 10 18:21:36 2018
OS/Arch: linux/amd64
Experimental: false
Orchestrator: swarm
Server:
Engine:
Version: 18.04.0-ce
API version: 1.37 (minimum version 1.12)
Go version: go1.9.4
Git commit: 3d479c0
Built: Tue Apr 10 18:25:25 2018
OS/Arch: linux/amd64
Experimental: false
10.2 啟動一個容器
# 啟動容器
[root@linux-host2 ~]# docker run -itd --name mycentos cgy/mycentos:v1 /bin/bash
56b03239e57c99802bba279d20f1437621269b74eb15d8d6a712c3f56f740541
# 進入容器查看分區大小
[root@linux-host2 ~]# docker attach mycentos
[root@ebec89c0ee40 /]# df -HT
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486 xfs 10G 375M 9.7G 4% /
tmpfs tmpfs 68M 0 68M 0% /dev
tmpfs tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/mapper/docker-root ext4 32G 462M 29G 2% /etc/hosts
shm tmpfs 68M 0 68M 0% /dev/shm
tmpfs tmpfs 2.0G 0 2.0G 0% /proc/scsi
tmpfs tmpfs 2.0G 0 2.0G 0% /sys/firmware
使用
ctrl+p+q
退出容器而不使其中斷。注意:容器mycentos的磁盤空間默認為10G左右,
/dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
就是容器mycentos的存儲設備文件名。
接下來就開始進行容器存儲空間的動態擴容
10.3 開始容器存儲空間動態擴容
使用dmsetup
查看該文件扇區信息.下面命令結果中的第二個數字(即20971520)是設備的大小,表示有20971520個 512-bytes 的扇區. 這個值(20971520*512bytes
)略高于 10GB 的大小。
[root@linux-host2 ~]# dmsetup table /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
0 20971520 thin 253:2 9
計算20G所需扇區數目
[root@linux-host2 ~]# echo $((20*1024*1024*1024/512))
41943040
將新的扇區大小寫入,注意只是改變舊表中的第二個數字20971520的數字,其他數字不變!
[root@linux-host2 ~]# echo 0 41943040 thin 253:2 9 | dmsetup load /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
將修改后的容器存儲文件激活
[root@linux-host2 ~]# dmsetup resume /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
重新查看文件信息
[root@linux-host2 ~]# dmsetup table /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
0 41943040 thin 253:2 9
更改文件系統大小,使變更生。
[root@linux-host2 ~]# xfs_growfs /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
meta-data=/dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486 isize=256 agcount=16, agsize=163824 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=2621184, imaxpct=25
= sunit=16 swidth=16 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=16 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
data blocks changed from 2621184 to 5242880
如果文件系統是ext2、ext3、ext4格式的,則要用
resize2fs <設備文件>
命令,使之變更。
如果是xfs文件系統,用resize2fs
命令去操作則會報如下錯誤:
[root@linux-host2 ~]# resize2fs /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
resize2fs 1.42.9 (28-Dec-2013)
resize2fs: Bad magic number in super-block while trying to open /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
Couldn't find valid filesystem superblock.
再次登錄mycentos容器,發現容器大小已經更新為20G左右!
[root@linux-host2 ~]# docker attach mycentos
[root@56b03239e57c /]#
[root@56b03239e57c /]#
[root@56b03239e57c /]# df -HT
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486 xfs 22G 394M 22G 2% /
tmpfs tmpfs 68M 0 68M 0% /dev
tmpfs tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/mapper/centos-root xfs 54G 5.2G 48G 10% /etc/hosts
shm tmpfs 68M 0 68M 0% /dev/shm
tmpfs tmpfs 2.0G 0 2.0G 0% /proc/scsi
tmpfs tmpfs 2.0G 0 2.0G 0% /sys/firmware
擴容后可能出現的問題:停止該容器后,無法重新啟動-
當容器擴容之后,由于dm認為設備塊大小仍然為之前設置的初始大小,所以會發生無法起啟動的情況,這時只要重新操作即可。
1)必須要先啟動一下,讓其生成dm文件才能修改
[root@linux-host2 ~]# docker start mycentos
//此時報錯不必理會,執行以下操作即可
[root@linux-host2 ~]# echo 0 41943040 thin 253:2 9 | dmsetup load /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
[root@linux-host2 ~]#
[root@linux-host2 ~]# dmsetup resume /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
[root@linux-host2 ~]#
[root@linux-host2 ~]# docker start mycentos
mycentos
為了方便后續容器動態擴容,可以采用下面的Dynamic_Modify_Docker_Disk.sh腳本(經測試可以使用)
#!/usr/bin/env bash
# This script is dynamic modify docker container disk
# Author Deng Lei
# 參數:
# $1 : 容器名稱或容器ID
# $2 : 擴容后的大小,默認單位是GB,只寫數字即可
if [ -z $1 ] || [ -z $2 ]; then
echo "Usage: container_name increase_capacity"
echo "\tsh `basename $0` <container_name> <size>"
echo "Example: I want increase 11G to test"
echo "The command is: sh `basename $0` test 11"
exit 1
fi
if [ `docker inspect $1 &>>/dev/null && echo 0 || echo 1` -eq 1 ];then
echo "ERROR: The container $1 is no exist!"
exit 1
fi
# 如果$2輸入的不是純數字,例如:20G,則$?為0,可以以此判斷$2輸入的是否為純數字
echo $2 | grep [^0-9] &>/dev/null && echo "ERROR: Size is a Pure digital" && exit 1
device_name=`docker inspect -f "{{.GraphDriver.Data.DeviceName}}" $1`
device_file=/dev/mapper/$device_name
now_disk=`dmsetup table $device_file | awk '{print $2}'`
disk=$(($2*1024*1024*1024/512))
if [ $disk -lt $now_disk ];then
echo "ERROR: I can't shink container $1 from $(($now_disk*512/1024/1024/1024))G to ${2}G!I only modify contanier increase disk!"
exit 1
fi
dmsetup table $device_file | sed "s/0 [0-9]* thin/0 $disk thin/" | dmsetup load $device_file
dmsetup resume $device_file
# 如果是ext2|ext3|ext4 請將如下xfs_growfs命令替換成resize2fs命令
xfs_growfs $device_file &>/dev/null
if [ $? -eq 0 ];then
echo -e "\033[1;32mDynamic expansion container $1 disk to ${2}G is success!\033[0m"
else
echo "Dynamic expansion container $1 disk to ${2}G is failed!"
fi
利用上述腳本給mycenos1容器動態擴容至25G
[root@docker ~]# chmod 755 dynamic_expansion_docker_disk.sh
[root@docker ~]# ./dynamic_expansion_docker_disk.sh mycentos1 25
dynamic container mycentos1 disk to 25G is success!
動態擴容后,對容器進行重啟,會發生報錯,此時再運行一次該腳本進行重新擴容(空間大小要等于或大于之前的設置,出現報錯不用管),再啟動容器即可(注意:docker容器目前是無法進行動態縮減的,僅能進行增加操作)。
延伸:
點擊查看根分區擴展容量:LVM根分區擴容
容器硬盤熱擴容和Docker鏡像和容器存放目錄修改方法:https://www.cnblogs.com/kevingrace/p/6667063.html
使用 Device Mapper來改變Docker 容器的大小:https://blog.csdn.net/feiskyer/article/details/41248123
11. Docker倉庫
11.1 將本地鏡像推送到公有倉庫
先查看一下本地的鏡像:
[root@linux-host2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cgy/mycentos v1 32f504582f68 33 hours ago 347MB
將本地cgy/mycentos:v1
這個鏡像打個標簽
[root@linux-host2 ~]# docker tag mycentos:1.0 cgy/mycentos:v1
因為docker默認是將鏡像推送到官方鏡像倉庫,所以你得先去hub.docker.com注冊一個賬號,然后再回來docker login
登錄,才能推送成功。
[root@linux-host2 ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: cgy0903 # 輸入用戶名
Password: # 輸入密碼
推送鏡像至公共倉庫:
[root@linux-host2 ~]# docker push mycentos:1.0
11.2 搭建私有鏡像倉庫
- 先pull一下官方的registry鏡像
[root@linux-host2 ~]# docker pull registry
- 運行容器
[root@linux-host2 ~]# docker run -d -p 5000:5000 --restart always --name registry registry:latest
d8532caa38586f40769c0c0e0c30d26227329270648b6d51c9cb3df5a0443f38
--restart always
:表示容器會在docker進程重啟后,立即跟著自己啟動,無須手動操作。
- 打標簽
Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
[root@linux-host2 ~]# docker tag mycentos:1.0 localhost:5000/mycentos:1.0
- 推送鏡像
[root@linux-host2 ~]# docker push localhost:5000/mycentos:1.0
The push refers to repository [localhost:5000/mycentos]
907467dd33d7: Pushed
43e653f84b79: Pushed
1.0: digest: sha256:57ab246be805bb5758d09cbcf874e5e4f94550428c7f365195fc254aebc9afc4 size: 741
速度快多了。
注意:雖然自建的私有倉庫速度快多了,但是還是感覺不好用,它沒用友好的交互界面。這就需要用到
harbor
了。
11.3 搭建harbor
harbor是VMWare開源的一個存儲和分發Docker鏡像的企業級注冊服務器,github地址:https://github.com/vmware/harbor 。Harbour提供更好的性能和安全性。此外,Harbor還提供高級安全功能,例如用戶管理,訪問控制和活動審計。
- 下載
$ wget https://github.com/vmware/harbor/archive/v1.4.0.tar.gz
- 解壓
[root@docker src]# tar xvf harbor-offline-installer-v1.4.0.tgz
# 進入安裝目錄下
[root@docker src]# cd harbor
- 修改配置
[root@docker harbor]# pwd
/usr/src/harbor
[root@docker harbor]# vim harbor.cfg
hostname = 192.168.1.7 # 主機名或IP,不可以是localhost或127.0.0.1
harbor_admin_password = Harbor12345 # web界面登錄密碼
我們只配置上述兩項即可,此外harbor.cfg中還有郵件發送、LDAP、以及數據庫相關配置,根據需要再進行配置即可。
- 安裝
[root@docker harbor]# ./install.sh
[Step 0]: checking installation environment ...
Note: docker version: 18.04.0
? Need to install docker-compose(1.7.1+) by yourself first and run this script again.
報錯:提示需要安裝docker-compose 1.7.1以上版本。
安裝docker-compose 1.9
[root@docker harbor]# yum list | grep docker-compose
docker-compose.noarch 1.9.0-5.el7 epel
[root@docker harbor]#
[root@docker harbor]# yum install -y docker-compose
再次安裝
[root@docker harbor]# ./install.sh
[Step 0]: checking installation environment ...
Note: docker version: 18.04.0
Note: docker-compose version: 1.9.0
[Step 1]: loading Harbor images ...
...
...
? ----Harbor has been installed and started successfully.----
Now you should be able to visit the admin portal at http://hub.cgy.com.
For more details, please visit https://github.com/vmware/harbor .
最后會提示安裝成功并成功啟動,
訪問htp://192.168.1.7
用戶名:admin (默認),密碼是harbor.cfg中
harbor_admin_password
配置的值。
使用很簡單,這里就不寫教程了。