牆裂推薦!看徹底面掌握,最詳細的 Docker 學習筆記總結(2021最新版)

Docker 是什麼?

Docker 是一個開源的容器引擎,能夠輕鬆的爲任何應用建立一個輕量級的、可移植的、自給自足的容器。開發者和系統管理員在筆記本上編譯測試經過的容器能夠批量地在生產環境中部署,包括 VMs(虛擬機)、bare metal、OpenStack 集羣、雲端、數據中心和其餘的基礎應用平臺。容器是徹底使用沙箱機制,相互之間不會有任何接口。php

爲啥要用Docker?

爲啥要用Docker?這要從目前軟件行業的痛點來說起html

  • 一、軟件更新發布及部署低效,過程繁瑣且須要人工介入
  • 二、環境一致性難以保證
  • 三、不一樣環境之間遷移成本過高

有了Docker能夠很大程度解決上面的問題。java

首先,Docker的使用簡單至極,從開發的角度來看就是三步走:構建,運輸,運行。其中關鍵步驟就是構建環節,即打包鏡像文件。可是從測試和運維的角度來看,那就只有兩步:複製,運行。有了這個鏡像,那麼想複製到哪運行均可以,徹底和平臺無關了。同時Docker這種容器技術隔離出了獨立的運行空間,不會和其餘應用爭用系統資源了以及還不須要考慮應用之間相互影響,想一想就開心。node

其次,由於在構建鏡像的時候就處理完了服務程序對於系統的全部依賴,因此在你使用的時候,你能夠忽略掉本來程序的依賴以及開發語言。對測試和運維而言,更多專一於本身的業務內容上。python

最後,Docker於開發者而言提供了一種開發環境的管理辦法,與測試人員而言保證了環境的同步,於運維人員提供了可移植的標準化部署流程。mysql

Docker 能幹啥?

  • 構建容易分發簡單
  • 隔離應用解除依賴
  • 快速部署測完就銷

Docker的應用場景在哪??

  1. 本地依賴(Local Dependency)

你須要在本地系統快速嘗試 Magento,或者爲一個項目使用 MySQL?仍是但願嘗試大部分開源項目?那就使用 Docker 吧,它將幫你節省大量時間。Docker 能提高開發者的開發效率,讓咱們快速搭建開發環境。 linux

開發環境的機器一般內存比較小,此前使用虛擬的時候,常常須要爲開發環境的機器加內存,而經過 Docker 能夠輕易的讓幾十個服務在 Docker 中跑起來。nginx

  1. 搭建環境(Build Environment)

若是你但願構建源碼,但發現沒有準備好合適的環境。 git

那麼使用 Docker是一個值得考慮的方案。畢竟若是使用傳統的方法一個一個地安裝軟件,一大堆軟件安裝下來確實十分費時間,使用容器技術省時省力,何樂而不爲?它能讓你將運行環境和配置放在代碼中而後部署,同一個 Docker 的配置能夠在不一樣的環境中使用,這樣就下降了硬件要求和應用環境之間耦合度。這裏有一個值得一看的例子: docker golang builder。github

  1. 微服務(Microservices)

你在使用微服務嗎?微服務架構將一個總體式的應用拆分紅松耦合的單個服務。

那不妨考慮一下 Docker,你能夠將每一個服務打包爲一個docker鏡像並使用docker-compose 來模擬生產環境(checkout docker networks)。最開始實踐的時候可能會比較費時費力,但長遠地來看,最終將產生巨大的生產力。

  1. 自動測試(Automated testing)

試想這樣一個問題,如何編寫自動化的集成測試用例,這些測試用例無需花很長時間來開始運行,使用者也可輕鬆管理。這裏不是指在 Docker 中運行測試用例,而是將測試用例與鏡像緊密運行在一塊兒。當你針對一個 docker 鏡像編寫測試用例時會有一個很大的優點。下面簡單介紹一下個人測試流程:運行兩個 docker 鏡像(app + db),在 MySQL 啓動時加載數據,並在 app docker 上使用 API。可查看此腳本以獲取快速的示例。

  1. 部署過程(Deployment process)

你能夠使用 docker 鏡像進行自我部署。許多主流的主機提供商都支持託管 docker,若是你擁有一個具備 shell 訪問權限的專用節點/vm,那麼事情將變得更容易。只須要設置好docker,並在你想要的端口上運行你的鏡像便可。

  1. 持續部署(Continuous Deployment)

都說 Docker 天生適合持續集成/持續部署,在部署中使用Docker,持續部署將變得很是簡單,並會在進入新的鏡像後從新開始。關於這個部分的自動化工做,如今已經有許多方案以供選擇,Kubernetes就是一個耳熟能詳的名字。Kubernetes是容器集羣管理系統,是一個開源的平臺,能夠實現容器集羣的自動化部署、自動擴縮容、維護等功能。

  1. 多租戶環境(Multi-tenancy)

Docker 有意思的一個使用場景是在多租戶的應用中,它能夠避免關鍵應用的重寫。若是你將應用程序服務公開給多個租戶(租戶指一組用戶,例如組織),使用單租戶方案設計的應用程序若是用上了 sub-domain + docker 能夠快速得到提供多租戶的服務。
關於這個場景的一個例子是爲物聯網的應用開發一個快速、易用的多租戶環境。這種多租戶的基本代碼很是複雜,很難處理,從新規劃這樣一個應用不但消耗時間,也浪費金錢。使用Docker,能夠爲每個租戶的應用層的多個實例建立隔離的環境,這不只簡單並且成本低廉,固然這一切得益於 Docker 環境的啓動速度和其高效的 diff 命令。

  1. 來自一臺機器的多個 APP(Multiple apps from one machine)

這與上面提到的微服務有些聯繫,但即便你沒有使用微服務,只是提供服務,Docker仍能夠很好地管理單個機器上的全部服務。你應該使用文件夾掛載來爲每一個基於數據的 docker 鏡像保留數據。

  1. 擴容 QPS(Scaling QPS)

Docker 經過建立另外一個容器來幫助你輕鬆地進行水平擴展。若是遇到巨大的高峯流量,Docker能夠幫助你解決問題 —— 只需添加更多的機器並增長負載均衡器背後運行的容器數量。

想全面瞭解的朋友能夠參考:太全了|萬字詳解Docker架構原理、功能及使用

Docker與Openstack對比

Docker 生態概覽

Docker安裝

root@centos7 ~]# yum install docker -y
[root@centos7 ~]# systemctl start docker

下載鏡像文件

[root@centos7 ~]# docker pull centos:latest
Trying to pull repository docker.io/library/centos ... 
centos7: Pulling from docker.io/library/centos
93857f76ae30: Pull complete 
Digest: sha256:4eda692c08e0a065ae91d74e82fff4af3da307b4341ad61fa61771cc4659af60
[root@centos7 ~]# docker images
REPOSITORY        TAG      IMAGE ID     CREATED     SIZE
docker.io/centos  centos7  a8493f5f50ff 3 days ago  192.5 MB

刪除鏡像

[root@centos7 ~]# docker rmi a8493f5f50ff    ##容器ID

Docker容器建立與管理

1)建立容器

方法一:

[root@centos7 ~]# docker run centos /bin/echo "nihao"  ##建立容器
nihao
[root@centos7 ~]# docker ps -a   ##查看全部容器
CONTAINER ID  IMAGE  COMMAND   CREATED    STATUS   PORTS    NAMES
3c113f9a4f1b centos "/bin/echo nihao" 43 seconds ago Exited (0) 41 seconds ago  boring_liskov

這裏沒有指定容器名稱,自動命名,狀態是自動退出

方法二:建立一個自定義名稱的容器

[root@centos7 ~]# docker run --name mgg -t -i centos /bin/bash
                              名稱  分配僞終端  -i 處於打開狀態
[root@2db7f1389dbd /]# ps -ef
UID   PID  PPID  C STIME TTY  TIME CMD
root   1    0  0 22:46 ?   00:00:00 /bin/bash
root   13   1  0 22:49 ?  00:00:00 ps -ef
[root@centos7 ~]# docker ps
CONTAINER ID  IMAGE   COMMAND   CREATED   STATUS  PORTS    NAMES
2db7f1389dbd  centos  "/bin/bash"  4 minutes ago   Up 4 minutes   mgg

docker ps -a是顯示全部容器包括沒有運行的(同virsh list --all)

2)進入、退出、啓動容器

[root@2db7f1389dbd /]# exit   ##退出容器
exit
[root@centos7 ~]# docker start 2db7f1389dbd   ##啓動容器
2db7f1389dbd
[root@centos7 ~]# docker attach 2db7f1389dbd  ##進入容器(必須是啓動狀態下)
[root@2db7f1389dbd /]# hostname
2db7f1389dbd

這種進入方式,退出後容器就進入Down狀態,以下

[root@2db7f1389dbd /]# exit
exit
[root@centos7 ~]# docker ps
CONTAINER ID   IMAGE  COMMAND   CREATED    STATUS    PORTS   NAMES

3)使用nsenter命令進入容器

[root@centos7 ~]# nsenter --help
Usage:
 nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.
Options:
 -t, --target <pid>     target process to get namespaces from
 -m, --mount[=<file>]   enter mount namespace
 -u, --uts[=<file>]     enter UTS namespace (hostname etc)
 -i, --ipc[=<file>]     enter System V IPC namespace
 -n, --net[=<file>]     enter network namespace
 -p, --pid[=<file>]     enter pid namespace
 -U, --user[=<file>]    enter user namespace
 -S, --setuid <uid>     set uid in entered namespace
 -G, --setgid <gid>     set gid in entered namespace
     --preserve-credentials do not touch uids or gids
 -r, --root[=<dir>]     set the root directory
 -w, --wd[=<dir>]       set the working directory
 -F, --no-fork          do not fork before exec'ing <program>
 -Z, --follow-context   set SELinux context according to --target PID
 -h, --help     display this help and exit
 -V, --version  output version information and exit

獲取容器的PID

[root@centos7 ~]# docker inspect --format "{{.State.Pid}}" 2db7f1389dbd 
4580
[root@centos7 ~]# nsenter -t 4580 -u -i -n -p
[root@2db7f1389dbd ~]# hostname
2db7f1389dbd
[root@2db7f1389dbd ~]# exit
logout
[root@centos7 ~]# docker ps
CONTAINER ID  IMAGE    COMMAND    CREATED    STATUS   PORTS  NAMES
2db7f1389dbd  centos    "/bin/bash" 22 minutes ago   Up 7 minutes  mgg

4)刪除容器

[root@centos7 ~]# docker ps -a
CONTAINER ID   IMAGE  COMMAND   CREATED     STATUS    PORTS    NAMES
2db7f1389dbd  centos  "/bin/bash"  31 minutes ago  Up 16 minutes  mgg
3c113f9a4f1b  centos  "/bin/echo nihao" 38 minutes ago Exited (0) 38 minutes ago boring_liskov
[root@centos7 ~]# docker rm 3c113f9a4f1b  ##接名稱也能夠,刪除一箇中止的容器
3c113f9a4f1b
[root@centos7 ~]# docker rm -f   3c113f9a4f1b ##刪除一個正在運行的容器
[root@centos7 ~]# docker ps -a          
CONTAINER ID  IMAGE   COMMAND    CREATED    STATUS    PORTS   NAMES
2db7f1389dbd    centos    "/bin/bash"    31 minutes ago   Up 16 minutes  mgg
[root@centos7 ~]# docker run --rm centos /bin/echo "hello"   ##建立時自動刪除,用於測試
[root@centos7 ~]#docker --kill $(docker ps -a -q)            ##刪除正在運行的容器

Docker網絡模式

Dokcer 經過使用 Linux 橋接提供容器之間的通訊,Docker的網絡模式有四種

分別是如下四種模式:

  • host 模式,使用--net=host 指定。
  • container 模式,使用--net=container:NAMEorID 指定。
  • none 模式,使用--net=none 指定。
  • bridge 模式,使用--net=bridge 指定,默認配置
  • host 模式

若是容器使用 host 模式,那麼容器將不會得到一個獨立的 Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出本身的網卡與配置 IP 等,而是使用宿主機的 IP 和端口。就和直接跑在宿主機中同樣。可是容器的文件系統、進程列表等仍是和宿主機隔離的。

  • container 模式

這個模式指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新建立的容器不會建立本身的網卡與配置 IP,而是和一個指定的容器共享 IP、端口範圍等。一樣,兩個容器除了網絡方面,其餘方面仍然是隔離的。

  • none模式

此模式不一樣於前兩種,Docker 容器有本身的 Network Namespace,可是,Docker容器沒有任何網絡配置。而是須要咱們手動給 Docker容器添加網卡、配置 IP 等。

  • bridge 模式

此模式是Docker默認的網絡設置,此模式會爲每個容器分配Network Namespace,並將一個主機上的Docker容器鏈接到一個虛擬網橋上。

更多關於Docker容器網絡介紹請參考:Docker容器網絡-基礎篇Docker容器網絡-實現篇

Docker數據存儲

docker管理數據的方式有兩種:

  • 數據卷
  • 數據卷容器

默認容器的數據是保存在容器的可讀寫層,當容器被刪除時其上的數據也會丟失,因此爲了實現數據的持久性則須要選擇一種數據持久技術來保存數據。官方提供了三種存儲方式:Volumes、Bind mounts和tmpfs。

數據存儲方式

從如今開始,咱們學習 Docker 容器的數據存儲方式,你也能夠先了解一下Docker 數據持久化的三種方案

Bind mount 會覆蓋容器中的文件,而 volume mount 則不會。即若是容器中已有文件,則會將文件同步到主機的目錄上。此方式與 Linux 系統的 mount 方式很類似,便是會覆蓋容器內已存在的目錄或文件,但並不會改變容器內原有的文件,當 umount 後容器內原有的文件就會還原。

數據卷(Volumes)

  • docker建立和管理,且與主機的核心功能隔離

  • 不管是命名仍是匿名數據卷,都存儲在/var/lib/docker/volumes/下面
  • 定義的數據卷能夠在多個容器中同時使用,且不會自動刪除
  • 容許容器將內容保存到遠端、雲服務提供商、加密內容等等

掛在主機目錄(Bind mounts)

  • 與數據卷相比,掛在主機目錄具備有限的功能
  • 應用的文件或者目錄事先不須要存在,用時會自動建立
  • 該方式容許訪問容器的敏感文件,可能會產生安全隱患

內存映射(tmpfs)

  • 僅存儲在容器的內存中,永遠不會寫入文件系統
  • swarm服務使用tmpfs掛載將敏感信息掛載到容器中

數據卷 - volumes

數據卷是存儲在 Docker 容器的特定目錄下面

優點說明

Docker Volumes 機制一般用來給 Docker 容器保存持久化數據,使用 Volumes 有不少優點:

  • 更容易進行備份和數據遷移
  • 使用 Docker CLI 命令或者 Docker API 來管理
  • 能夠在 Linux 和 Windows 操做系統上使用
  • 能夠更安全得在多個容器中共享
  • Volume drivers 容許容器將內容保存到遠端、雲服務提供商、加密 volume 內容
  • 新 Volume 的內容能夠被容器預先填充

Volumes 一般也優於容器的可寫層,使用 Volumes 不會增長容器的體積,而且 Volumes 的內容存儲在外部獨立於容器的生命週期。若是容器不產生持久化數據,能夠考慮使用 tmpfs 內存映射(只保存在容器的內存中)的方式來避免數據存儲在其餘可能的地方,避免增長容器的體積。

使用說明

最開始的時候 -v 或者 --volume 選項是給單獨容器使用,而 --mount 選項是給集羣服務使用。可是從 Docker 17.06 開始,也能夠在單獨容器上使用 --mount。一般來說 --mount 選項也更加具體和詳細。-v 選項將全部選項集中到一個值,而 --mount 選項將可選項分開。若是須要指定 volume driver 選項,那麼必須使用 --mount 選項。

# 建立一個數據卷
$ docker volume create my-vol

# 查看全部的數據卷
$ docker volume ls

# 查看指定數據卷的信息
$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

# 移除指定數據卷的
$ docker volume rm my-vol

# 清除無主的數據卷
$ docker volume prune
# 啓動一個掛載數據卷的容器
$ docker run -d -P --name web \
    -v my-vol:/wepapp \
    training/webapp python app.py

$ docker run -d -P --name web \
    --mount source=my-vol,target=/webapp \
    training/webapp python app.py

# 啓動一個掛載數據卷的服務
$ docker service create -d --name devtest-service \
    --mount source=myvol2,target=/app \
    nginx:latest
# 掛載爲只讀模式
$ docker run -d --name=nginxtest \
    -v nginx-vol:/usr/share/nginx/html:ro \
    nginx:latest

# type能夠分爲bind、volume、tmpfs, 默認爲volume
# source用於設置數據卷的名稱,匿名數據卷能夠省略
# target表示須要掛載到容器裏面的地方
# readonly表示掛載的內容爲只讀模式,可選
# volume-opt表示能夠使用屢次,可選
$ docker run -d --name=nginxtest \
    --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
    nginx:latest
[3] 掛載遠程數據卷
# 插件sshfs容許您輕鬆地在容器中掛載遠程文件夾

# 下載該插件
$ docker plugin install --grant-all-permissions vieux/sshfs

# 使用該驅動建立ssh數據卷
$ docker volume create --driver vieux/sshfs \
    -o sshcmd=test@node2:/home/test \
    -o password=testpassword \
    -o port=3336 \
    sshvolume

# 啓動該驅動程序建立卷建立容器
# 若是兩個容器配置了可信關係,就不須要設置volume-opt密碼了
$ docker run -d \
    --name sshfs-container \
    --volume-driver vieux/sshfs \
    --mount src=sshvolume,target=/app, \
    volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
    nginx:latest

掛載主機目錄 - bind mounts

掛載主機目錄是將主機中的特定目錄直接掛在到容器內部使用

使用說明
# 使用bind模式啓動容器
$ docker run -d -it --name devtest \
    -v "$(pwd)"/target:/app \
    nginx:latest

$ docker run -d -it --name devtest \
    --mount type=bind,source="$(pwd)"/target,target=/app \
    nginx:latest

# 看下對應的信息
$ docker inspect devtest
"Mounts": [
    {
        "Type": "bind",
        "Source": "/tmp/source/target",
        "Destination": "/app",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
]

# 掛載爲只讀模式
$ docker run -d -it --name devtest \
    -v "$(pwd)"/target:/app:ro \
    nginx:latest

$ docker run -d -it --name devtest \
    --mount type=bind,source="$(pwd)"/target,target=/app,readonly \
    nginx:latest

特殊屬性

$ docker run -d -it --name devtest \
    -v "$(pwd)"/target:/app \
    -v "$(pwd)"/target:/app2:ro,rslave \
    nginx:latest

$ docker run -d -it --name devtest \
    --mount type=bind,source="$(pwd)"/target,target=/app \
    --mount type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave \
    nginx:latest

內存映射 - tmpfs

內存映射是將內存映射到容器內供容器內部使用

優點說明

最開始 --tmpfs 是給單獨容器使用,而 --mount 選項是給 swarm 集羣服務使用的。可是,從 Docker 17.06 開始,也能夠在單獨容器上使用 --mount 了。一般說來,--mount 更明確,更冗長。最大的區別是 --tmpfs 標誌不支持任何可配置選項。其中 --tmpfs 只能在容器中使用,而 swarm 集羣則必須使用 --mount 來使用 tmpfs 內存映射。

使用說明

# 容器上使用
$ docker run -d -it --name tmptest \
    --tmpfs /app \
    nginx:latest

$ docker run -d -it --name tmptest \
    --mount type=tmpfs,destination=/app \
    nginx:latest

日誌驅動 - logs

在容器外部查看容器內部的日誌輸出狀況,便於排除和監控問題

能夠利用 docker logs 命令,查看 Docker 容器內部應用程序運行時所產生的日誌。能夠免除首先進入 Docker 容器,再打開應用程序的日誌文件的過程。docker logs 會監控容器中操做系統的標準輸出設備(STDOUT),一旦 STDOUT 有數據產生,就會將這些數據傳輸到另外一個設備中,則被稱爲日誌驅動(Logging Driver)。

# 動態查看日誌內容
$ docker logs -f netdata
Docker 是怎樣作到的呢?咱們使用 docker info 命令,能夠看到 Docker 容器的相關信息,其中有一項 Logging Driver 的字段。

# 當前所設置的日誌驅動類型
$ docker info | grep 'Logging Driver'
Logging Driver: json-file

咱們能夠在 docker run 命令中經過 --log-driver 參數來設置具體的 Docker 日誌驅動,也能夠經過 --log-opt 參數來指定對應日誌驅動的相關選項。

docker run -d -p 80:80 --name nginx \    
--log-driver json-file \ # 設置日誌驅動    
--log-opt max-size=10m \ # 表示JSON文件最大爲10MB,超過則生成新的文件    
--log-opt max-file=3 \   # 表示JSON文件最多保存3個,超過則刪除多餘文件    
nginx
# 固然,能夠在配置文件中添加,全局生效
$ cat /etc/docker/daemon.json
{
  "log-driver": "syslog"
}

# 修改配置以後重啓服務
$ sudo systemctl restart docker

額外,須要注意的是,默認狀況下,Docker 將日誌存儲到一個日誌文件。

# 檢查日誌文件路徑
$ docker inspect --format='{{.LogPath}}' netdata
/var/lib/docker/containers/556553bcb5xxx13cbc588a4-json.log

# 查看實時日誌信息
$ tail -f `docker inspect --format='{{.LogPath}}' netdata`

上述內容參考: https://escapelife.github.io/...

Docker Command 介紹

安裝完成docker容器服務以後,須要瞭解如何操做它?在shell命令行下直接輸入docker就能夠查看幫助信息,以下。

[root@master ~]# docker
Usage:    docker COMMAND
A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -D, --debug              Enable debug mode
      --help               Print usage
  -H, --host list          Daemon socket(s) to connect to (default [])
  -l, --log-level string   Set the logging level ("debug", "info", "warn", "error", "fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  container   Manage containers
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  volume      Manage volumes

Commands:
  attach      Attach to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

命令不少,重點介紹這20個,請詳細閱讀下面的文章:

這20個Docker Command,有幾個是你會的?

Docker file

Docker file簡單介紹

Docker能夠使用Dockerfile的內容來自動構建鏡像。Dockerfile也是一個文件,其中有建立鏡像、運行指令等一系列的命令,且每行只支持一個運行命令。

Docker file分爲四部分組成:

  • 基礎鏡像信
  • 維護者信息
  • 鏡像操做指令
  • 容器啓動時執行指令

dockerfile指令忽略大小寫,建議大寫,#做爲註釋,每行只支持一條指令,指令能夠帶多個參數。

dockerfile指令有:

  • 構建指令:用於構建image,其指定的操做不會在運行image的容器中執行。
  • 設置指令:用於設置image的屬性,其指定的操做會在運行image的容器中執行。

Dockerfile指令

Dockerfile指令一共有如下種:

  • 一、FROM

用來指定基礎鏡像,而後經過在基礎鏡像上構建新的鏡像,基礎鏡像通常有遠程或本地倉庫。而且Dockerfile文件第一行必須的FROM指令,若是一個Dockerfile須要建立多個鏡像,能夠使用多個FROM指令。

#具體使用用法以下:
FROM < image_name >   #默認是latest版本
FROM <image:version>  #指定版本
  • 二、MAINTAINER

指定鏡像的建立者信息

#具體使用法以下:
MAINTAINER < name >
  • 三、RUN

運行全部基礎鏡像能支持的命令,一樣也能夠使用多條RUN指令,能夠使用\來換行

#具體使用法以下:
RUN < command >
RUN ["executable", "param1", "param2" ... ] (exec form)
  • 四、CMD

用於容器啓動時的指定操做,它能夠是命令,也能夠是腳本,但只執行一次,若是有多少默認只會執行最後一個。

#具體使用法以下:
CMD [「executable」 ,」Param1」, 「param2」]使用exec執行,推薦 
CMD command param1 param2,在/bin/sh上執行 
CMD [「Param1」, 「param2」] 提供給ENTRYPOINT作默認參數。
  • 五、EXPOSE

指定容器的端口映射(容器與物理機),運行容器時加上-p參數指定EXPOSE設置的端口。EXPOSE能夠設置多個端口號,相應地運行容器配套屢次使用-p參數。能夠經過docker port +容器須要映射的端口號和容器ID來參考宿主機的映射端口。

#具體使用法以下:
EXPOSE <port> [port1 , port2 ............]
  • 六、ENV

在鏡像中用於設置環境變量的,而後RUN命令能夠使用此設置的環境變量,在容器啓動後也以經過docker inspect查看環境變量,能夠經過docker run --env key=value來設置或修改環境變量。

#具體使用法以下:
ENV <key> <value>
ENV JAVA_HOME /usr/local/jdk
  • 七、ADD

複製指定的源文件、目錄、URL到容器的指定目錄中。全部拷貝到container中的文件和文件夾權限爲0755,uid和gid爲0。

若是源是一個目錄,那麼會將該目錄下的全部文件添加到container中,不包括目錄;

若是源文件是可識別的壓縮格式,則docker會幫忙解壓縮(注意壓縮格式);

若是源是文件且目標目錄中不使用斜槓結束,則會將目標目錄視爲文件,源的內容會寫入目標目錄;

若是源是文件且目標目錄中使用斜槓結束,則會源文件拷貝到目標目錄下。

#具體使用法以下:
ADD <源> <目標>
  • 八、COPY

複製本地主機的源(默認爲Dockerfile所在的目錄)到容器中的目標中,目標路徑不存在時會自動建立。

#具體使用法以下:
COPY <源> <目標>
COPY web/index.html  /var/web/
  • 路徑必須是絕對路徑,若是不存在,會自動建立對應目錄
  • 路徑必須是Dockerfile 所在路徑的相對路徑
  • 若是是一個目錄,只會複製目錄下的內容,而目錄自己則不會被複制
  • 九、ENTRYPOINT

指定容器啓動後執行的命令,多行只執行最後一行。而且不可被docker run提供的參數覆蓋。

#具體使用法以下:
ENTRYPOINT "command" "param1" "param2"
  • 十、VOLUME

建立一個能夠從本地主機或其它容器掛載的掛載點,通常用於存放數據。與docker run -v也能夠實現此功能。

#具體使用法以下:
VOLUME  [directory_name]
VOLUME /docker_data
  • 十一、USER

指定容器運行時使用的用戶或UID,後面RUN、CMD、ENTRYPIONT都會使用此用戶來運行命令。

#具體使用法以下:
USER [username/uid]
  • 十二、WORKDIR

指定RUN、CMD、ENTRYPIONT指定的命令的運行目錄。能夠使用多個WORKDIR指令,後續參數若是是相對路徑,則會基於以前的命令指定的路徑。如:WORKDIR /data WORKDIR work。最終的路徑就是/data/work。path路徑也能夠是環境變量。

#具體使用方法以下:
WORKDIR [path]
  • 1三、ONBUILD

配置當前所建立的鏡像做爲其它新建立鏡像的基礎鏡像時,所執行的操做指令。就是,這個鏡像建立後,若是其它鏡像以這個鏡像爲基礎,會先執行這個鏡像的ONBUILD命令。

#具體使用法以下:
ONBUILD [INSTRUCTION]

經過Dockerfile快速構建鏡像

接下來,咱們經過構建一個Tomcat鏡像,來演示Dockerfile的使用方法,前提是安裝Docker環境,如何安裝Docker環境就不在此贅述了。請猛戳下面的文字:

[root@master tomcat]# ll
總用量 190504
-rw-r--r-- 1 root root   9552281 6月   7 15:07 apache-tomcat-8.5.31.tar.gz
-rw-r--r-- 1 root root        32 7月   3 09:41 index.jsp
-rw-r--r-- 1 root root 185515842 9月  20 2017 jdk-8u144-linux-x64.tar.gz
[root@master tomcat]# cat index.jsp 
welcome to mingongge's web site
[root@master tomcat]# pwd
/root/docker/tomcat
[root@master tomcat]# vim Dockerfile
#config file start#
FROM centos
MAINTAINER mingongge <微信公衆號:民工哥技術之路>

#add jdk and tomcat software
ADD jdk-8u144-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.31.tar.gz /usr/local/
ADD index.jsp /usr/local/apache-tomcat-8.5.31/webapps/ROOT/

#config java and tomcat ENV
ENV JAVA_HOME /usr/local/jdk1.8.0_144
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.31/
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

#config listen port of tomcat
EXPOSE 8080

#config startup command of tomcat
CMD /usr/local/apache-tomcat-8.5.31/bin/catalina.sh run

#end of config-file#

構建過程

[root@master tomcat]# docker build -t tomcat-web . #這個.不用註釋了吧相信懂的人天然懂的
Sending build context to Docker daemon 195.1 MB
Step 1/11 : FROM centos
 ---> 49f7960eb7e4
Step 2/11 : MAINTAINER mingongge <微信公衆號:民工哥技術之路>
 ---> Running in afac1e218299
 ---> a404621fac22
Removing intermediate container afac1e218299
Step 3/11 : ADD jdk-8u144-linux-x64.tar.gz /usr/local/
 ---> 4e22dafc2f76
Removing intermediate container b1b23c6f202a
Step 4/11 : ADD apache-tomcat-8.5.31.tar.gz /usr/local/
 ---> 1efe59301d59
Removing intermediate container aa78d5441a0a
Step 5/11 : ADD index.jsp /usr/local/apache-tomcat-8.5.31/webapps/ROOT/
 ---> f09236522370
Removing intermediate container eb54e6eb963a
Step 6/11 : ENV JAVA_HOME /usr/local/jdk1.8.0_144
 ---> Running in 3aa91b03d2d1
 ---> b497c5482fe0
Removing intermediate container 3aa91b03d2d1
Step 7/11 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
 ---> Running in f2649b5069be
 ---> 9cedb218a8df
Removing intermediate container f2649b5069be
Step 8/11 : ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.31/
 ---> Running in 39ef620232d9
 ---> ccab256164fe
Removing intermediate container 39ef620232d9
Step 9/11 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
 ---> Running in a58944d03d4a
 ---> f57de761a759
Removing intermediate container a58944d03d4a
Step 10/11 : EXPOSE 8080
 ---> Running in 30681437d265
 ---> b906dcc26584
Removing intermediate container 30681437d265
Step 11/11 : CMD /usr/local/apache-tomcat-8.5.31/bin/catalina.sh run
 ---> Running in 437790cc642a
 ---> 95204158ee68
Removing intermediate container 437790cc642a
Successfully built 95204158ee68

經過構建的鏡像啓動容器

[root@master tomcat]# docker run -d -p 8080:8080 tomcat-web
b5b65bee5aedea2f48edb276c543c15c913166bf489088678c5a44fe9769ef45
[root@master tomcat]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED        STATUS         PORTS                    NAMES
b5b65bee5aed   tomcat-web   "/bin/sh -c '/usr/..."   5 seconds ago  Up 4 seconds   0.0.0.0:8080->8080/tcp   vigilant_heisenberg

訪問容器

瀏覽器輸入http://server-ip:8080, 結果以下:

Docker三劍客

容器技術|Docker三劍客之Compose

容器技術|Docker三劍客之docker-machine

打造高逼格、可視化的Docker容器監控系統平臺

私有鏡像倉庫搭建

當咱們執行docker pull xxx的時候,docker默認是從registry.docker.com這個地址上去查找咱們所須要的鏡像文件,而後執行下載操做。這類的鏡像倉庫就是docker默認的公共倉庫,全部人均可以直接查看或下載、使用,可是呢,基於網絡緣由,下載速度有限制比較慢。所以,咱們在公司內部內網環境中使用dokcer,通常不會將鏡像文件上傳到公網公共庫中。但內部共享使用就是個問題,因此,私有倉庫就由此產生了。

什麼是私有倉庫?

私有倉庫,就是本地(內網環境)組建的一個與公網公共庫功能類似的鏡像倉庫。組建好以後,咱們就能夠將打包好的鏡像提交到私有倉庫中,這樣內網其它用戶也能夠使用這個鏡像文件。

本文使用官方提供的registry鏡像來組建企業內網的私有鏡像倉庫

環境介紹

兩臺安裝好docker環境的主機

  • 服務端:192.168.3.82 私有倉庫服務器在,運行registry容器
  • 客戶端:192.168.3.83 測試客戶端,用於上傳、下載鏡像文件

安裝佈署過程

下載官方registry鏡像文件

[root@master ~]# docker pull registry
Using default tag: latest
Trying to pull repository docker.io/library/registry ... 
latest: Pulling from docker.io/library/registry
81033e7c1d6a: Pull complete 
b235084c2315: Pull complete 
c692f3a6894b: Pull complete 
ba2177f3a70e: Pull complete 
a8d793620947: Pull complete 
Digest: sha256:672d519d7fd7bbc7a448d17956ebeefe225d5eb27509d8dc5ce67ecb4a0bce54
Status: Downloaded newer image for docker.io/registry:latest
[root@master ~]# docker images |grep registry
docker.io/registry   latest  d1fd7d86a825   5 months ago  33.3 MB

運行registry容器

[root@master ~]# mkdir /docker/registry -p
[root@master ~]# docker run -itd -v /docker/registry/:/docker/registry -p 5000:5000 --restart=always --name registry registry:latest
26d0b91a267f684f9da68f01d869b31dbc037ee6e7bf255d8fb435a22b857a0e
[root@master ~]# docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED        STATUS        PORTS                    NAMES
26d0b91a267f   registry:latest  "/entrypoint.sh /e..."   4 seconds ago  Up 3 seconds  0.0.0.0:5000->5000/tcp   registry

參數說明

1)-itd:在容器中打開一個僞終端進行交互操做,並在後臺運行;
2)-v:把宿主機的/docker/registry目錄綁定到容器/docker/registry目錄(這個目錄是registry容器中存放鏡像文件的目錄),來實現數據的持久化;
3)-p:映射端口;訪問宿主機的5000端口就訪問到registry容器的服務了;
4)--restart=always:這是重啓的策略,假如這個容器異常退出會自動重啓容器;
5)--name registry:建立容器命名爲registry,可自定義任何名稱;
6)registry:latest:這個是剛纔pull下來的鏡像;

查看遠程倉庫鏡像文件

[root@master ~]# curl http://localhost:5000/v2/_catalog
{"repositories":[]}

一樣也能夠使用瀏覽器訪問http://server-ip:5000/v2/_cat... 結果相同,都是空的沒有任何文件。

客戶端操做

修改下載的鏡像源

[root@slave1 ~]# vim /etc/docker/daemon.json
{
"registry-mirrors":["https://registry.docker-cn.com"]
}
[root@slave1 ~]# systemctl restart docker

下載測試鏡像

[root@slave1 ~]# docker pull nginx
Using default tag: latest
Trying to pull repository docker.io/library/nginx ... 
latest: Pulling from docker.io/library/nginx
683abbb4ea60: Pull complete 
6ff57cbc007a: Pull complete 
162f7aebbf40: Pull complete 
Digest: sha256:636dd2749d9a363e5b57557672a9ebc7c6d041c88d9aef184308d7434296feea
Status: Downloaded newer image for docker.io/nginx:latest

給鏡像打TAG

[root@slave1 ~]# docker tag nginx:latest 192.168.3.82:5000/nginx:v1
[root@slave1 ~]# docker images
REPOSITORY                TAG       IMAGE ID        CREATED       SIZE
192.168.3.82:5000/nginx   v1        649dcb69b782    8 hours ago   109 MB
docker.io/nginx           latest    649dcb69b782    8 hours ago   109 MB

上傳鏡像

[root@slave1 ~]# docker push 192.168.3.82:5000/nginx:v1
The push refers to a repository [192.168.3.82:5000/nginx]
Get https://192.168.3.82:5000/v1/_ping: http: server gave HTTP response to HTTPS client
#注意這裏出現報錯提示,從提示信息能夠看出須要使用https的方式才能上傳,解決方案以下:
[root@slave1 ~]# vim /etc/docker/daemon.json
{
"registry-mirrors":["https://registry.docker-cn.com"],
 "insecure-registries":["192.168.3.82:5000"]
}
#添加私有鏡像服務器的地址,注意書寫格式爲json,有嚴格的書寫要求,須要重啓docker服務生效配置
[root@slave1 ~]# systemctl restart docker
[root@slave1 ~]# docker push 192.168.3.82:5000/nginx:v1
The push refers to a repository [192.168.3.82:5000/nginx]
6ee5b085558c: Pushed 
78f25536dafc: Pushed 
9c46f426bcb7: Pushed 
v1: digest: sha256:edad5e71815c79108ddbd1d42123ee13ba2d8050ad27cfa72c531986d03ee4e7 size: 948

從新查看鏡像倉庫

[root@master ~]# curl http://localhost:5000/v2/_catalog
{"repositories":["nginx"]}
[root@master ~]# curl http://localhost:5000/v2/nginx/tags/list
{"name":"nginx","tags":["v1"]}
#查看有哪些版本

測試下載

#首先刪除客戶端主機以前從公共庫下載下來的鏡像文件
[root@slave1 ~]# docker images
REPOSITORY                TAG      IMAGE ID        CREATED        SIZE
192.168.3.82:5000/nginx   v1       649dcb69b782    10 hours ago   109 MB
docker.io/nginx           latest   649dcb69b782    10 hours ago   109 MB
[root@slave1 ~]# docker image rmi -f 649dcb69b782
Untagged: 192.168.3.82:5000/nginx:v1
Untagged: 192.168.3.82:5000/nginx@sha256:edad5e71815c79108ddbd1d42123ee13ba2d8050ad27cfa72c531986d03ee4e7
Untagged: docker.io/nginx:latest
Untagged: docker.io/nginx@sha256:636dd2749d9a363e5b57557672a9ebc7c6d041c88d9aef184308d7434296feea
Deleted: sha256:649dcb69b782d4e281c92ed2918a21fa63322a6605017e295ea75907c84f4d1e
Deleted: sha256:bf7cb208a5a1da265666ad5ab3cf10f0bec1f4bcb0ba8d957e2e485e3ac2b463
Deleted: sha256:55d02c20aa07136ab07ab47f4b20b97be7a0f34e01a88b3e046a728863b5621c
Deleted: sha256:9c46f426bcb704beffafc951290ee7fe05efddbc7406500e7d0a3785538b8735
[root@slave1 ~]# docker images
REPOSITORY       TAG             IMAGE ID        CREATED         SIZE
#此時客戶端全部的鏡像文件所有刪除
[root@slave1 ~]# docker pull 192.168.3.82:5000/nginx:v1
Trying to pull repository 192.168.3.82:5000/nginx ... 
v1: Pulling from 192.168.3.82:5000/nginx
683abbb4ea60: Pull complete 
6ff57cbc007a: Pull complete 
162f7aebbf40: Pull complete 
Digest: sha256:edad5e71815c79108ddbd1d42123ee13ba2d8050ad27cfa72c531986d03ee4e7
Status: Downloaded newer image for 192.168.3.82:5000/nginx:v1
[root@slave1 ~]# docker images
REPOSITORY                TAG     IMAGE ID       CREATED         SIZE
192.168.3.82:5000/nginx   v1      649dcb69b782   11 hours ago    109 MB
#能夠看出,客戶端已正常從遠端服務器拉取到所須要的鏡像文件,其它內網服務器也能夠正常共享這臺鏡像服

以上步驟就是經過使用docker Registry快速搭建私有鏡像倉庫的過程與測試。我也其實也能夠經過:利用 Harbor 搭建企業級私有鏡像倉庫

Docker可視化工具

Docker是一項很是流行的容器技術,如今在各行各業有着普遍的使用。不過如何管理Docker容器是一個問題,因此我今天向你們介紹兩款Docker可視化工具,但願對你們有所幫助。

Portainer

Portainer是一款Docker可視化管理工具,容許咱們在網頁中方便的查看和管理Docker容器。

要使用Portainer很簡單,運行下面兩條命令便可。這些命令會建立一個Portainer專用的卷,而後在8000和9000端口建立容器並運行。

$ docker volume create portainer_data$ docker run --name portainer -d -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

而後在瀏覽器打開對應地址,就會發現成功運行了。第一次運行的時候須要設置帳號,而後選擇要管理的Docker主機。

設置帳號

選擇要管理的主機

以後就能夠看到本機上運行的Docker容器了,點擊它們還能夠進行容器的管理。左邊的條目能夠管理卷、建立容器、查看主機信息等等。基本上該有的功能都有了,這也是我推薦的一個工具。

LazyDocker

LazyDocker是基於終端的一個可視化查詢工具,支持鍵盤操做和鼠標點擊。相比Portainer來講可能不那麼專業,不過對於開發者來講可能反而更加好用了。由於通常開發者都是使用命令行來運行Docker,偶爾須要圖形化查看的時候,就能夠使用LazyDocker這個工具。

官網演示圖

安裝LazyDocker也很是簡單,運行下面的命令便可。

docker run --rm -it -v \/var/run/docker.sock:/var/run/docker.sock \-v ~/.config/lazydocker:/.config/jesseduffield/lazydocker \lazyteam/lazydocker

固然若是發現LazyDocker挺好用,準備常用的話,還能夠把它作成縮寫添加到shell配置文件中,這樣就能夠將它變成一個簡單的命令。例如我用的是zsh,就將下面這樣添加到.zshrc文件中。之後就能夠直接用lzd來調用LazyDocker了。

alias lzd='docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker lazyteam/lazydocker'

而後就能夠在終端中查看Docker容器、鏡像和卷的信息了。LazyDocker支持鍵盤操做和鼠標點擊,直接用鼠標點擊就能夠查看對應信息了。

須要注意若是你的終端LazyDocker的圖形顯示的是亂的,不用擔憂,只不過是顯示字體的問題。從新設置一下終端字體就能夠解決了。

以上內容來自:https://www.toutiao.com/i6780...

Docker 社區已經建立了許多開源工具,它們能幫咱們處理各類用例。做者在本文中推薦了 5 款認爲最有用的 Docker 工具,分別是 Watchtower(自動更新 Docker 容器)、docker-gc(容器和鏡像的垃圾回收)、docker-slim(容器瘦身)、 rocker:突破 Dockerfile 的限制,以及 ctop(容器的類頂層接口)。
Docker 社區已經建立了許多開源工具,它們所能幫你處理的用例甚至會超出你的想象。
你能夠在網上找到不少酷炫的 Docker 工具,其中大部分是開源的,均可以在 Github 上找到。在過去的兩年裏,我很是熱衷於 Docker,在大多數開發項目中都使用了它。當你開始使用 Docker 後,你會發現它適用的場景比你最初預想的還更多。你會但願 Docker 儘量爲你多作一點事,而它不會讓你失望的!
Docker 社區很是活躍,天天都會出現許多有用的工具,時時關注社區中發生的全部創新是很困難的。爲了幫助你,我收集了一些我在平常工做中使用的又有趣又實用的 Docker 工具,這些工具提高了個人工做效率,減小了本來須要手工完成的工做。

向你們推薦一些實用工具:你應該知道的5個開源Docker工具...,Docker 服務終端 UI 管理工具,你們最終根據本身的使用習慣與實際生產需求來選擇合適本身的工具來管理Docker容器。

Docker容器監控系統

隨着線上服務的全面docker化,對docker容器的監控就很重要了。SA的監控系統是物理機的監控,在一個物理機跑多個容器的狀況下,咱們是無法從一個監控圖表裏面區分各個容器的資源佔用狀況的。

推薦你們看看這篇:打造高逼格、可視化的Docker容器監控系統平臺

Docker 日誌管理最佳實踐

10 個冷門但又很是實用的 Docker 使用技巧

在平時的工做中,docker 接觸得不少,除了常用的 docker run ,docker stop 等命令,docker 還有不少十分有用可是卻不常用的命令,下面就來總結一下:

1. docker top

這個命令是用來查看一個容器裏面的進程信息的,好比你想查看一個 nginx 容器裏面有幾個 nginx 進程的時候,就能夠這麼作:

docker top 3b307a09d20d
UID      PID    PPID    C    STIME  TTY    TIME       CMD
root     805    787     0    Jul13   ?   00:00:00  nginx: master process nginx -g daemon off;
systemd+ 941     805     0   Jul13    ?   00:03:18  nginx: worker process

2. docker load && docker save

我通常使用這兩個命令去下載打包 Kubernetes 的鏡像,由於你知道的國內的網速並不像國外那麼快。

docker save 能夠把一個鏡像保存到 tar 文件中,你能夠這麼作:

~ docker save registry:2.7.1 >registry-2.7.1.tar
#同時 docker load 能夠把鏡像從 tar 文件導入到 docker 中
~ docker load < registry-2.7.1.tar

3. docker search

這個命令能夠幫助你在命令行中方便的搜索 DockerHub 中的鏡像,好比:

~ docker search nginx
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                              Official build of Nginx.                        13519               [OK]
jwilder/nginx-proxy                Automated Nginx reverse proxy for docker con…   1846                                    [OK]
richarvey/nginx-php-fpm            Container running Nginx + PHP-FPM capable of…   780                                     [OK]
linuxserver/nginx                  An Nginx container, brought to you by LinuxS…   123
bitnami/nginx                      Bitnami nginx Docker Image                      87                                      [OK]
tiangolo/nginx-rtmp                Docker image with Nginx using the nginx-rtmp…   85                                      [OK]
jc21/nginx-proxy-manager           Docker container for managing Nginx proxy ho…   73
alfg/nginx-rtmp                    NGINX, nginx-rtmp-module and FFmpeg from sou…   71                                      [OK]
nginxdemos/hello                   NGINX webserver that serves a simple page co…   57                                      [OK]
jlesage/nginx-proxy-manager        Docker container for Nginx Proxy Manager        53                                      [OK]
nginx/nginx-ingress                NGINX Ingress Controller for Kubernetes         37
......

固然這個功能在國內可能不會特別好用,由於......

4. docker events

這個命令能夠幫助你實時獲取 docker 的各類事件信息,好比建立了一個容器什麼的。

~ docker events
2020-07-28T21:28:46.000403018+08:00 image load sha256:432bf69f0427b52cad10897342eaf23521b7d973566354118e9a59c4d31b5fae (name=sha256:432bf69f0427b52cad10897342eaf23521b7d973566354118e9a59c4d31b5fae)

5. docker update

當你 docker run 了以後卻發現裏面有一些參數並非你想要的狀態好比你設置的 nginx 容器 cpu 或者內存過小,這個時候你就能夠使用 docker update 去修改這些參數。

~ docker update nginx --cpus 2

6. docker history

當你修改了一個鏡像,可是忘記了每一層的修改命令,或者你想查看一個鏡像是怎麼構建的時候就能夠使用這個命令,好比:

~ docker history  traefik:v2.1.6
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
5212a87ddaba        5 months ago        /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>           5 months ago        /bin/sh -c #(nop)  CMD ["traefik"]              0B
<missing>           5 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["/entrypoint.…   0B
<missing>           5 months ago        /bin/sh -c #(nop)  EXPOSE 80                    0B
<missing>           5 months ago        /bin/sh -c #(nop) COPY file:59a219a1fb7a9dc8…   419B
<missing>           5 months ago        /bin/sh -c set -ex;  apkArch="$(apk --print-…   52.9MB
<missing>           5 months ago        /bin/sh -c apk --no-cache add ca-certificate…   1.85MB
<missing>           6 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           6 months ago        /bin/sh -c #(nop) ADD file:a1906f14a4e217a49…   4.81MB

7. docker wait

這個命令能夠查看容器的退出狀態,好比:

~ docker wait 7f7f0522a7d0
0

這樣你就能夠知道這個容器是正常退出的仍是異常退出的了。

8. docker pause && docker unpause

當你運行了一個容器可是想要暫停它運行的時候,你就能夠使用這個命令。

~ docker pause 7f7f0522a7d0

9. docker diff

當你運行了一個容器,可是你不知道容器裏修改了哪一些文件的時候能夠使用這個命令,好比:

~ docker diff 38c59255bf6e
C /etc
A /etc/localtime
C /var
C /var/lib
A /var/lib/registry

10. docker stats

這個是 docker 內置的監控命令,當你想要查看當前主機下全部容器佔用內存和 cpu 的狀況的時候就能夠使用這個命令。

~ docker stats

CONTAINER ID        NAME                        CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
1c5ade04e7f9        redis                        0.08%               17.53MiB / 47.01GiB   0.04%               10.9GB / 37GB       0B / 0B             4
afe6d4ebe409        kafka-exporter                0.09%               16.91MiB / 47.01GiB   0.04%               1.97GB / 1.53GB     752MB / 0B          23
f0c7c01a9c34        kafka-docker_zookeeper         0.01%               308.8MiB / 47.01GiB   0.64%               20.2MB / 12.2MB     971MB / 3.29MB      28
da8c5008955f        kafka-docker_kafka-manager     0.08%               393.2MiB / 47.01GiB   0.82%               1.56MB / 2.61MB     1.14GB / 0B         60
c8d51c583c49        kafka-docker_kafka            1.63%               1.256GiB / 47.01GiB   2.67%               30.4GB / 48.9GB     22.3GB / 5.77GB     85
......

原文:http://suo.im/6n2lLa

學習Docker,新手最容易犯的11個錯誤!

不少人最終仍是決定使用 Docker 解決問題。 Docker 的優勢不少,好比:

  • 一、一體化——將操做系統、庫版本、配置文件、應用程序等所有打包裝在容器裏。從而保證 QA 所測試的鏡像 (image) 會攜帶一樣的行爲到達生產環境。
  • 二、輕量——內存佔用極小,只爲主要過程分配內存。
  • 三、快讀——一鍵啓動,就像啓動常見的 linux 過程同樣快。

儘管如此,衆多用戶仍然只是把容器當作常見的虛擬機,而忘記了容器的一個重要特性:
正由於這一特色,一些用戶須要改變他們對容器的觀念,爲了更好的使用與發揮 Docker 容器的價值,有一些事情是絕對不該該作的:

1.不要在容器(container)中存儲數據

容器可能會被中斷、被替換或遭到破壞。在容器中運行的 1.0 版應用程序很容易就會被 1.1 版取代,而不會對數據形成影響或致使數據丟失。所以,若是須要存儲數據,請存儲在卷 (volume) 中。在這一狀況下,還應注意兩個容器是否會在同一個捲上寫入數據,這將致使損壞。請確保應用程序適用於寫入共享的數據存儲。

2. 不要分兩部分傳送應用程序 有些人把容器看成虛擬機

因此他們大多會認爲,應該將應用程序部署到現有正在運行的容器中。在須要不斷部署和調試的開發階段,可能確實如此;但對於 QA 和生產的持續交付 (CD) 渠道,應用程序應當是鏡像的一部分。切記:容器轉瞬即逝。

3. 不要建立大尺寸鏡像

大尺寸的鏡像難以分配。請確保僅使用必需文件和庫來運行應用程序。不要安裝沒必要要的數據包,也不要運行「更新」(yum update),這些操做會把大量文件下載到新的鏡像層。

4. 不要使用單層鏡像

爲了有效利用多層文件系統,請始終爲操做系統建立屬於本身的基本鏡像層,而後爲用戶名定義建立一個層,爲運行時安裝建立一個層,爲配置建立一個層,最後再爲應用程序建立一個層。這樣,從新建立、管理和分配鏡像就會容易些。

5. 不要從正在運行的容器中建立鏡像

換句話說,不要使用"docker commit"命令來建立鏡像。這一鏡像建立方法不可複製,所以應徹底避免使用。請始終使用 Dockerfile 或其餘任何可徹底複製的 S21(從源代碼到鏡像)方法,如此一來,若是存儲在源代碼控制存儲庫 (GIT) 中,就能夠跟蹤 Dockerfile 的變動狀況。

6. 不要只使用「最新版」標籤

最新版標籤就像 Maven 用戶的「快照」(SNAPSHOT) 同樣。容器具備多層文件系統這一基本特徵,因此咱們鼓勵使用標籤。相信誰也不肯意在構建了幾個月的鏡像後,忽然發現應用程序由於父層(即 Dockerfile 中的 FROM)被新版本取代而沒法運行(新版本沒法向後兼容或從構建緩存中檢索的「最新「版有誤)這樣的意外吧?在生產過程當中部署容器時也應避免使用」最新版「標籤,這是由於沒法跟蹤當前運行的鏡像版本。

7. 不要在單個容器中運行一個以上進程

容器只運行一個進程(HTTP 守護進程、應用程序服務器、數據庫)時效果最佳,但若是運行一個以上進程,在管理和檢索日誌以及單獨更新進程時就會遇到不少麻煩。

8. 不要在鏡像中存儲證書及使用環境變量

不要在鏡像中對任何用戶名/密碼進行硬編碼操做。請使用環境變量從容器外部檢索信息。Postgres 鏡像就是這一原理的極佳詮釋。

9. 不要以 root 權限運行進程

「默認狀況下,Docker 容器以 root 用戶權限運行。隨着 Docker 技術日趨成熟,可以使用的安全默認選項愈來愈多。目前,要求 root 對其餘用戶來講較爲危險,另外,不是全部環境都可以使用 root。鏡像應使用 USER 指令來爲容器的運行指定非 root 用戶。」(摘自《Docker 鏡像做者指南》(Guidance for Docker Image Authors))

10. 不要依賴 IP 地址

每一個容器都有本身的內部 IP 地址,若是啓動而後中止容器,內部 IP 地址可能會發生變化。若是你的應用程序或微服務須要和另外一個容器進行通訊,請使用環境變量在容器之間傳遞相應的主機名和端口。

11. 監控容器 Docker

監控已經愈來愈受到開發者們的重視,實時監控 Docker 的方法,這裏推薦 Cloudinsight。 不一樣於一些須要自寫腳本的監控手段,Cloudinsight 做爲一家免費的 SaaS 服務,可以一鍵監控 Docker,且擁有很棒的可視化界面。除此以外,Cloudinsight 還支持多種操做系統、數據庫等的監控,可以一體化展現全部被監控的系統基礎組件的性能數據。

原文:https://my.oschina.net/cllgee...

Jenkins與Docker的自動化CI/CD實戰

1、發佈流程設計

工做流程:

  • 開發人員提交代碼到Git版本倉庫;
  • Jenkins人工/定時觸發項目構建;
  • Jenkins拉取代碼、代碼編碼、打包鏡像、推送到鏡像倉庫;
  • Jenkins在Docker主機建立容器併發布。

3、 部署過程

1,部署git

若是公司內部有直接克隆就能夠

git clone git@192.168.0.31:/home/git/solo.git

2,部署Jenkins環境

部署傳送門:Jenkins+Maven+Svn實現代碼自動打包與發佈

3,部署私有鏡像倉庫

注意:docker 倉庫 因爲https 認證,全部須要pull的客戶端,須要修改配置文件

[root@linux-node1 ~]# vim /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
 OPTIONS='--selinux-enabled --insecure-registry 192.168.56.11:5000'

4,全部主機安裝docker

1)安裝依賴包
yum install -y yum-utils device-mapper-persistent-data lvm2`
 
2)添加Docker軟件包源:
yum-config-manager 
--add-repo 
https://download.docker.com/linux/centos/docker-ce.repo

3)安裝Docker CE
 yum install docker-ce -y`
 
4)配置加速器
 curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://bc437cce.m.daocloud.io`
 #由於默認源會去國外獲取數據,因此會慢能夠超時,這是咱們就須要配置加速器指向國內源https://www.daocloud.io/
 
5)啓動並開機啓動
# systemctl start docker
# systemctl enable docker

4、構建基礎鏡像

【Apache、Nginx、Tomcat、LNMP、LAMP、LNTP】

JAVA程序必須有JDK環境才能夠運行,爲了減小鏡像大小及提升性能,這裏直接把JDK放到宿主機上,容器以掛載形式使用。

1,安裝jdk

#rz 把tar包上傳,解壓後放到指定目錄
rz....... 
tar -zxvf jdk-8u60-linux-x64.tar.gz
mv jdk1.8.0_60 /usr/local/jdk1.8

2,擬寫Dockerfile

# cat Dockerfile
FROM centos:7
#他的媽媽是誰
MAINTAINER www.aliangedu.com
#他的爸爸是誰
ENV VERSION=8.5.33
#tomcat版本
ENV JAVA_HOME /usr/local/jdk
#jdk 絕對路徑
RUN yum install wget -y
#運行的命令
RUN wget http://mirrors.shu.edu.cn/apache/tomcat/tomcat-8/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz && 
 tar zxf apache-tomcat-${VERSION}.tar.gz && 
 mv apache-tomcat-${VERSION} /usr/local/tomcat && 
 rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* && 
 mkdir /usr/local/tomcat/webapps/ROOT
EXPOSE 8080
#程序使用的端口
CMD /usr/local/tomcat/bin/catalina.sh run
#執行tomcat目錄下的啓動腳本,這裏面遇到坑,就是-v 將宿主機jdk目錄掛在到容器/usr/local/jdk 時候,由於鏡像按照dockerfile去打,那麼在執行命令的時候就會找不到路徑,因此我臨時刪除了,EXPOSE與CMD 2行,而後從新打包,使用 -p 指定端口,而後進入容器,手工啓動tomcat的方式,進行

3,構建鏡像

docker build -t 192.168.56.11:5000/tomcat-85:latest -f dockerfile . 
#最後這個點。表明當前路徑,在製做鏡像時,會記錄上下文內容

4,上傳到docker 鏡像倉庫

root@node02 scripts]# docker push 192.168.56.11:5000/tomcat-85:latest

5,啓動鏡像 測試

[root@node02 scripts]# docker run -it -d -p 8080:8080 -v /usr/local/jdk1.8:/usr/local/jdk 192.168.56.11:5000/tomcat-8:latest
[root@3addff07c464 ROOT]# echo "123" >index.jsp

5、Jenkins 配置

1.主頁面 -> 系統管理 -> 全局工具配置

指定JDK、Maven路徑,Git保持默認:

2.jenkins安裝必要插件

主頁面 -> 系統管理 ->管理插件:

安裝SSH與Git Parameter插件。

插件說明:

  • 》SSH:用於SSH遠程Docker主機執行Shell命令
  • 》Git Parameter:動態獲取Git倉庫Branch、Tag

3,配置SSH插件

第一步:先建立一個用於鏈接Docker主機的憑證 (有權限的用戶)

主頁面 -> 憑據 -> 系統 -> 右擊全局憑據 -> 添加憑據:

輸入鏈接Docker主機的用戶名和密碼:

第二步:添加SSH遠程主機

主頁面 -> 系統管理 -> 系統設置 -> SSH remote hosts:

問題:當以普通用戶身份去使用docker images時,出現如下錯誤:

6、將從github上下載的JAVA項目,上傳到本身的gitlab倉庫

# git clone https://github.com/b3log/solo
# cd solo
移除舊的推送地址,添加新的:
# git remote remove origin 
# git remote add origin git@gitlab.example.com:qqq/solo.git
提交代碼到Git倉庫並建立tag:
# touch src/main/webapp/a.html
# git add .
# git commit -m 「a」
建立標籤:
# git tag 1.0.0
推送到Git服務器:
# git push origin 1.0.0

登錄gitlab查看solo項目:

7、Jenkins建立項目併發布測試

1.主頁面 -> 新建任務 -> 輸入任務名稱,構建一個Maven項目:

注意:若是沒有顯示「構建一個Maven項目」選項,須要在管理插件裏安裝「Maven Integration plugin」插件。

配置Git參數化構建:

2.動態獲取Git倉庫tag,與用戶交互選擇Tag發佈:【也能夠設置分支】

3.指定項目Git倉庫地址:

修改*/master爲$Tag,Tag是上面動態獲取的變量名,表示根據用戶選擇打代碼版本。

4.設置maven構建命令選項:

clean package -Dmaven.test.skip=ture

利用pom.xml文件構建項目。

在Jenkins本機鏡像構建與推送到鏡像倉庫,並SSH遠程鏈接到Docker主機使用推送的鏡像建立容器:

上圖中 命令內容以下:

REPOSITORY=192.168.56.11:5000/solo:${Tag}
# 構建鏡像
cat > Dockerfile << EOF
FROM 192.168.56.11:5000/tomcat-8:latest
RUN rm -rf /usr/local/tomcat/webapps/ROOT
COPY target/*.war /usr/local/tomcat/webapps/ROOT.war
CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]
EOF
docker build -t $REPOSITORY .
# 上傳鏡像
docker push $REPOSITORY


上圖中Command 內容以下:

REPOSITORY=192.168.56.11:5000/solo:${Tag}
# 部署
sudo docker rm -f blog-solo |true
sudo docker image rm $REPOSITORY |true
sudo docker container run -d --name blog-solo -v /usr/local/jdk1.8:/usr/local/jdk -p 8080:8080 $REPOSITORY
# -d 後臺運行 ,-v 掛在目錄,-p 映射端口,後面是鏡像

注:容器名稱blog-solo,暴露宿主機端口8080,即便用宿主機IP 192.168.56.12:8080 訪問blog-solo項目。

blog-solo項目已配置完成,開始構建:

選擇tag,開始構建:

點擊左下角構建歷史裏,右擊第一個查看控制檯輸出:

構建詳細內容

構建成功

訪問:192.168.56.12:8080 查看部署結果

調整項目訪問地址

進入容器,切換到項目目錄

vi WEB-INF/classes/latke.properties 
#### Server ####
# Browser visit protocol
serverScheme=http
# Browser visit domain name
serverHost=192.168.56.12
# Browser visit port, 80 as usual, THIS IS NOT SERVER LISTEN PORT!
serverPort=8080

調整後,重啓tomcat,再次驗證,OK,結果以下:

至此,自動化CI環境搭建完成,你能夠模擬提交代碼並打tag測試自動化發佈流程。

8、問題總結:

查看docker.sock權限

[root@node03 ~]# ll /var/run/docker.sock 
srw-rw---- 1 root docker 0 9月 4 21:55 /var/run/docker.sock

解決方法:【免sudo 使用docker images 】

[root@node03 ~]# sudo groupadd docker
 ##groupadd:「docker」組已存在
[root@node03 ~]# sudo gpasswd -a jenkins docker
 ##正在將用戶「jenkins」加入到「docker」組中
[root@node03 ~]# sudo service docker restart
##重啓服務
[root@node03 ~]# newgrp - docker
##從新加載group 組信息,必定要輸入這條命令,不然沒法加載最新組內容,由於有緩存

原文:https://www.toutiao.com/a6602...

使用 GitLab CI 和 Docker 自動部署 Spring Boot 應用

Docker 常見疑難雜症解決方案

圖片

這裏主要是爲了記錄在使用 Docker 的時候遇到的問題及其處理解決方法。

圖片

1.Docker 遷移存儲目錄

默認狀況系統會將 Docker 容器存放在/var/lib/docker 目錄下

問題原由:今天經過監控系統,發現公司其中一臺服務器的磁盤快慢,隨即上去看了下,發現 /var/lib/docker 這個目錄特別大。由上述緣由,咱們都知道,在 /var/lib/docker 中存儲的都是相關於容器的存儲,因此也不能隨便的將其刪除掉。

那就準備遷移 docker 的存儲目錄吧,或者對 /var 設備進行擴容來達到相同的目的。更多關於 dockerd 的詳細參數,請點擊查看 官方文檔 地址。

可是須要注意的一點就是,儘可能不要用軟鏈, 由於一些 docker 容器編排系統不支持這樣作,好比咱們所熟知的 k8s 就在內。

# 發現容器啓動不了了
ERROR:cannot  create temporary directory!
# 查看系統存儲狀況
$ du -h --max-depth=1

解決方法1:添加軟連接

# 1.中止docker服務
$ sudo systemctl stop docker
# 2.開始遷移目錄
$ sudo mv /var/lib/docker /data/
# 3.添加軟連接
# sudo ln -s /data/docker /var/lib/docker
# 4.啓動docker服務
$ sudo systemctl start docker

解決方法2:改動 docker 配置文件

# 3.改動docker啓動配置文件
$ sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --graph=/data/docker/
# 4.改動docker啓動配置文件
$ sudo vim /etc/docker/daemon.json
{
    "live-restore": true,
    "graph": [ "/data/docker/" ]
}

操做注意事項:在遷移 docker 目錄的時候注意使用的命令,要麼使用 mv 命令直接移動,要麼使用 cp 命令複製文件,可是須要注意同時複製文件權限和對應屬性,否則在使用的時候可能會存在權限問題。若是容器中,也是使用 root 用戶,則不會存在該問題,可是也是須要按照正確的操做來遷移目錄。

# 使用mv命令
$ sudo mv /var/lib/docker /data/docker
# 使用cp命令
$ sudo cp -arv /data/docker /data2/docker

下圖中,就是由於啓動的容器使用的是普通用戶運行進程的,且在運行當中須要使用 /tmp 目錄,結果提示沒有權限。在咱們導入容器鏡像的時候,實際上是會將容器啓動時須要的各個目錄的權限和屬性都賦予了。若是咱們直接是 cp 命令單純複製文件內容的話,就會出現屬性不一致的狀況,同時還會有必定的安全問題。

圖片

2.Docker 設備空間不足

Increase Docker container size from default 10GB on rhel7.

問題原由一:容器在導入或者啓動的時候,若是提示磁盤空間不足的,那麼多半是真的由於物理磁盤空間真的有問題致使的。以下所示,咱們能夠看到 / 分區確實滿了。

# 查看物理磁盤空間
$ df -Th
Filesystem    Size    Used    Avail    Use%    Mounted on
/dev/vda1      40G     40G       0G    100%    /
tmpfs         7.8G       0     7.8G      0%    /dev/shm
/dev/vdb1     493G    289G     179G     62%    /mnt

若是發現真的是物理磁盤空間滿了的話,就須要查看究竟是什麼佔據瞭如此大的空間,致使由於容器沒有空間沒法啓動。其中,docker 自帶的命令就是一個很好的可以幫助咱們發現問題的工具。

# 查看基本信息
# 硬件驅動使用的是devicemapper,空間池爲docker-252
# 磁盤可用容量僅剩16.78MB,可用供咱們使用
$ docker info
Containers: 1
Images: 28
Storage Driver: devicemapper
 Pool Name: docker-252:1-787932-pool
 Pool Blocksize: 65.54 kB
 Backing Filesystem: extfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 1.225 GB
 Data Space Total: 107.4 GB
 Data Space Available: 16.78 MB
 Metadata Space Used: 2.073 MB
 Metadata Space Total: 2.147 GB

解決方法:經過查看信息,咱們知道正是由於 docker 可用的磁盤空間不足,因此致使啓動的時候沒有足夠的空間進行加載啓動鏡像。解決的方法也很簡單,第一就是清理無效數據文件釋放磁盤空間(清除日誌),第二就是修改 docker 數據的存放路徑(大分區)。

# 顯示哪些容器目錄具備最大的日誌文件
$ du -d1 -h /var/lib/docker/containers | sort -h
# 清除您選擇的容器日誌文件的內容
$ cat /dev/null > /var/lib/docker/containers/container_id/container_log_name

問題原由二:顯然我遇到的不是上一種狀況,而是在啓動容器的時候,容器啓動以後不久就顯示是 unhealthy 的狀態,經過以下日誌發現,原來是複製配置文件啓動的時候,提示磁盤空間不足。

後面發現是由於 CentOS7 的系統使用的 docker 容器默認的建立大小就是 10G 而已,然而咱們使用的容器卻超過了這個限制,致使沒法啓動時提示空間不足。

2019-08-16 11:11:15,816 INFO spawned: 'app-demo' with pid 835
2019-08-16 11:11:16,268 INFO exited: app (exit status 1; not expected)
2019-08-16 11:11:17,270 INFO gave up: app entered FATAL state, too many start retries too quickly
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device

解決方法1:改動 docker 啓動配置文件

# /etc/docker/daemon.json
{
    "live-restore": true,
    "storage-opt": [ "dm.basesize=20G" ]
}

解決方法2:改動 systemctl 的 docker 啓動文件

# 1.stop the docker service
$ sudo systemctl stop docker
# 2.rm exised container
$ sudo rm -rf /var/lib/docker
# 2.edit your docker service file
$ sudo vim /usr/lib/systemd/system/docker.service
# 3.find the execution line
ExecStart=/usr/bin/dockerd
and change it to:
ExecStart=/usr/bin/dockerd --storage-opt dm.basesize=20G
# 4.start docker service again
$ sudo systemctl start docker
# 5.reload daemon
$ sudo systemctl daemon-reload

問題原由三:還有一種狀況也會讓容器沒法啓動,並提示磁盤空間不足,可是使用命令查看發現並非由於物理磁盤真的不足致使的。而是,由於對於分區的 inode 節點數滿了致使的。

# 報錯信息
No space left on device

解決方法:由於 ext3 文件系統使用 inode table 存儲 inode 信息,而 xfs 文件系統使用 B+ tree 來進行存儲。考慮到性能問題,默認狀況下這個 B+ tree 只會使用前 1TB 空間,當這 1TB 空間被寫滿後,就會致使沒法寫入 inode 信息,報磁盤空間不足的錯誤。咱們能夠在 mount 時,指定 inode64 便可將這個 B+ tree 使用的空間擴展到整個文件系統。

# 查看系統的inode節點使用狀況
$ sudo df -i
# 嘗試從新掛載
$ sudo mount -o remount -o noatime,nodiratime,inode64,nobarrier /dev/vda1

補充知識:文件儲存在硬盤上,硬盤的最小存儲單位叫作「扇區」(Sector)。每一個扇區儲存 512 字節(至關於0.5KB)。操做系統讀取硬盤的時候,不會一個個扇區地讀取,這樣效率過低,而是一次性連續讀取多個扇區,即一次性讀取一個「塊」(block)。這種由多個扇區組成的」塊」,是文件存取的最小單位。」塊」的大小,最多見的是4KB,即連續八個 sector 組成一個 block 塊。文件數據都儲存在」塊」中,那麼很顯然,咱們還必須找到一個地方儲存文件的元信息,好比文件的建立者、文件的建立日期、文件的大小等等。這種儲存文件元信息的區域就叫作「索引節點」(inode)。每個文件都有對應的 inode,裏面包含了除了文件名之外的全部文件信息。

inode 也會消耗硬盤空間,因此硬盤格式化的時候,操做系統自動將硬盤分紅兩個區域。一個是數據區,存放文件數據;另外一個是 inode 區(inode table),存放 inode 所包含的信息。每一個 inode 節點的大小,通常是 128 字節或 256 字節。inode 節點的總數,在格式化時就給定,通常是每1KB或每2KB就設置一個 inode 節點。

# 每一個節點信息的內容
$ stat check_port_live.sh
  File: check_port_live.sh
  Size: 225           Blocks: 8          IO Block: 4096   regular file
Device: 822h/2082d    Inode: 99621663    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: ( 1006/  escape)   Gid: ( 1006/  escape)
Access: 2019-07-29 14:59:59.498076903 +0800
Modify: 2019-07-29 14:59:59.498076903 +0800
Change: 2019-07-29 23:20:27.834866649 +0800
 Birth: -
# 磁盤的inode使用狀況
$ df -i
Filesystem                 Inodes   IUsed     IFree IUse% Mounted on
udev                     16478355     801  16477554    1% /dev
tmpfs                    16487639    2521  16485118    1% /run
/dev/sdc2               244162560 4788436 239374124    2% /
tmpfs                    16487639       5  16487634    1% /dev/shm

3.Docker 缺共享連接庫

Docker 命令須要對/tmp 目錄下面有訪問權限

問題原由:給系統安裝完 compose 以後,查看版本的時候,提示缺乏一個名爲 libz.so.1 的共享連接庫。第一反應就是,是否是系統少安裝那個軟件包致使的。隨即,搜索了一下,將相關的依賴包都給安裝了,卻仍是提示一樣的問題。

# 提示錯誤信息
$ docker-compose --version
error while loading shared libraries: libz.so.1: failed to map segment from shared object: Operation not permitted

解決方法:後來發現,是由於系統中 docker 沒有對 /tmp 目錄的訪問權限致使,須要從新將其掛載一次,就能夠解決了。

# 從新掛載
$ sudo mount /tmp -o remount,exec

4.Docker 容器文件損壞

對 dockerd 的配置有可能會影響到系統穩定

問題原由:容器文件損壞,常常會致使容器沒法操做。正常的 docker 命令已經沒法操控這臺容器了,沒法關閉、重啓、刪除。正巧,前天就須要這個的問題,主要的緣由是由於從新對 docker 的默認容器進行了從新的分配限制致使的。

# 操做容器遇到相似的錯誤
b'devicemapper: Error running deviceCreate (CreateSnapDeviceRaw) dm_task_run failed'

解決方法:能夠經過如下操做將容器刪除/重建。

# 1.關閉docker
$ sudo systemctl stop docker
# 2.刪除容器文件
$ sudo rm -rf /var/lib/docker/containers
# 3.從新整理容器元數據
$ sudo thin_check /var/lib/docker/devicemapper/devicemapper/metadata
$ sudo thin_check --clear-needs-check-flag /var/lib/docker/devicemapper/devicemapper/metadata
# 4.重啓docker
$ sudo systemctl start docker

5.Docker 容器優雅重啓

不中止服務器上面運行的容器,重啓 dockerd 服務是多麼好的一件事

問題原由:默認狀況下,當 Docker 守護程序終止時,它會關閉正在運行的容器。從 Docker-ce 1.12 開始,能夠在配置文件中添加 live-restore 參數,以便在守護程序變得不可用時容器保持運行。須要注意的是 Windows 平臺暫時仍是不支持該參數的配置。

# Keep containers alive during daemon downtime
$ sudo vim /etc/docker/daemon.yaml
{
  "live-restore": true
}
# 在守護進程停機期間保持容器存活
$ sudo dockerd --live-restore
# 只能使用reload重載
# 至關於發送SIGHUP信號量給dockerd守護進程
$ sudo systemctl reload docker
# 可是對應網絡的設置須要restart才能生效
$ sudo systemctl restart docker

解決方法:能夠經過如下操做將容器刪除/重建。

# /etc/docker/daemon.yaml
{
    "registry-mirrors": ["https://vec0xydj.mirror.aliyuncs.com"],  # 配置獲取官方鏡像的倉庫地址
    "experimental": true,  # 啓用實驗功能
    "default-runtime": "nvidia",  # 容器的默認OCI運行時(默認爲runc)
    "live-restore": true,  # 重啓dockerd服務的時候容易不終止
    "runtimes": {  # 配置容器運行時
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "default-address-pools": [  # 配置容器使用的子網地址池
        {
            "scope": "local",
            "base":"172.17.0.0/12",
            "size":24
        }
    ]
}

6.Docker 容器沒法刪除

找不到對應容器進程是最嚇人的

問題原由:今天遇到 docker 容器沒法中止/終止/刪除,覺得這個容器可能又出現了 dockerd 守護進程託管的狀況,可是經過ps -ef <container id>沒法查到對應的運行進程。哎,後來開始開始查 supervisor 以及 Dockerfile 中的進程,都沒有。這種狀況的可能緣由是容器啓動以後,以後,主機因任何緣由從新啓動而且沒有優雅地終止容器。剩下的文件如今阻止你從新生成舊名稱的新容器,由於系統認爲舊容器仍然存在。

# 刪除容器
$ sudo docker rm -f f8e8c3..
Error response from daemon: Conflict, cannot remove the default name of the container

解決方法:找到 /var/lib/docker/containers/ 下的對應容器的文件夾,將其刪除,而後重啓一下 dockerd 便可。咱們會發現,以前沒法刪除的容器沒有了。

# 刪除容器文件
$ sudo rm -rf /var/lib/docker/containers/f8e8c3...65720
# 重啓服務
$ sudo systemctl restart docker.service

7.Docker 容器中文異常

容器存在問題話,記得優先在官網查詢

問題原由:今天登錄以前部署的 MySQL 數據庫查詢,發現使用 SQL 語句沒法查詢中文字段,即便直接輸入中文都沒有辦法顯示。

# 查看容器支持的字符集
root@b18f56aa1e15:# locale -a
C
C.UTF-8
POSIX

解決方法:Docker 部署的 MySQL 系統使用的是 POSIX 字符集。然而 POSIX 字符集是不支持中文的,而 C.UTF-8 是支持中文的只要把系統中的環境 LANG 改成 "C.UTF-8" 格式便可解決問題。同理,在 K8S 進入 pod 不能輸入中文也可用此方法解決。

# 臨時解決
docker exec -it some-mysql env LANG=C.UTF-8 /bin/bash
# 永久解決
docker run --name some-mysql 
    -e MYSQL_ROOT_PASSWORD=my-secret-pw 
    -d mysql:tag --character-set-server=utf8mb4 
    --collation-server=utf8mb4_unicode_ci

8.Docker 容器網絡互通

瞭解 Docker 的四種網絡模型

問題原由:在本機部署 Nginx 容器想代理本機啓動的 Python 後端服務程序,可是對代碼服務以下的配置,結果訪問的時候一直提示 502 錯誤。

# 啓動Nginx服務
$ docker run -d -p 80:80 $PWD:/etc/nginx nginx
nginx
server {
    ...
    location /api {
        proxy_pass http://localhost:8080
    }
    ...
}

解決方法:後面發現是由於 nginx.conf 配置文件中的 localhost 配置的有問題,因爲 Nginx 是在容器中運行,因此 localhost 爲容器中的 localhost,而非本機的 localhost,因此致使沒法訪問。

能夠將 nginx.conf 中的 localhost 改成宿主機的 IP 地址,就能夠解決 502 的錯誤。

# 查詢宿主機IP地址 => 172.17.0.1
$ ip addr show docker0
docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:d5:4c:f2:1e brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d5ff:fe4c:f21e/64 scope link
       valid_lft forever preferred_lft forever
nginx
server {
    ...
    location /api {
        proxy_pass http://172.17.0.1:8080
    }
    ...
}

當容器使用 host 網絡時,容器與宿主共用網絡,這樣就能在容器中訪問宿主機網絡,那麼容器的 localhost 就是宿主機的 localhost 了。

# 服務的啓動方式有所改變(沒有映射出來端口)
# 由於自己與宿主機共用了網絡,宿主機暴露端口等同於容器中暴露端口
$ docker run -d -p 80:80 --network=host $PWD:/etc/nginx nginxx

9.Docker 容器總線錯誤

總線錯誤看到的時候仍是挺嚇人了

問題原由:在 docker 容器中運行程序的時候,提示 bus error 錯誤。

# 總線報錯
$ inv app.user_op --name=zhangsan
Bus error (core dumped)

解決方法:緣由是在 docker 運行的時候,shm 分區設置過小致使 share memory 不夠。不設置 –shm-size 參數時,docker 給容器默認分配的 shm 大小爲 64M,致使程序啓動時不足。

# 啓動docker的時候加上--shm-size參數(單位爲b,k,m或g)
$ docker run -it --rm --shm-size=200m pytorch/pytorch:latest

解決方法:還有一種狀況就是容器內的磁盤空間不足,也會致使 bus error 的報錯,因此清除多餘文件或者目錄,就能夠解決了。

# 磁盤空間不足
$ df -Th
Filesystem     Type     Size  Used Avail Use% Mounted on
overlay        overlay    1T    1T    0G 100% /
shm            tmpfs     64M   24K   64M   1% /dev/shm

10.Docker NFS 掛載報錯

總線錯誤看到的時候仍是挺嚇人了

問題原由:咱們將服務部署到 openshift 集羣中,啓動服務調用資源文件的時候,報錯信息以下所示。從報錯信息中,得知是在 Python3 程序執行 read_file() 讀取文件的內容,給文件加鎖的時候報錯了。可是奇怪的是,本地調試的時候發現服務都是能夠正常運行的,文件加鎖也是沒問題的。後來發現,在 openshift 集羣中使用的是 NFS 掛  載的共享磁盤。

# 報錯信息
Traceback (most recent call last):
    ......
    File "xxx/utils/storage.py", line 34, in xxx.utils.storage.LocalStorage.read_file
OSError: [Errno 9] Bad file descriptor
# 文件加鎖代碼
...
    with open(self.mount(path), 'rb') as fileobj:
        fcntl.flock(fileobj, fcntl.LOCK_EX)
        data = fileobj.read()
    return data
...

解決方法:從下面的信息得知,要在 Linux 中使用 flock() 的話,就須要升級內核版本到 2.6.11+ 才行。後來才發現,這其實是由 RedHat 內核中的一個錯誤引發的,並在 kernel-3.10.0-693.18.1.el7 版本中獲得修復。因此對於 NFSv3 和 NFSv4 服務而已,就須要升級 Linux 內核版本纔可以解決這個問題。

# https://t.codebug.vip/questions-930901.htm
$ In Linux kernels up to 2.6.11, flock() does not lock files over NFS (i.e.,
the scope of locks was limited to the local system). [...] Since Linux 2.6.12,
NFS clients support flock() locks by emulating them as byte-range locks on the entire file.

11.Docker 默認使用網段


啓動的容器網絡沒法相互通訊,非常奇怪!

問題原由:咱們在使用 Docker 啓動服務的時候,發現有時候服務以前能夠相互連通,而有時間啓動的多個服務以前卻出現了沒法訪問的狀況。究其緣由,發現原來是由於使用的內部私有地址網段不一致致使的。有點服務啓動到了 172.17 - 172.31 的網段,有的服務跑到了 192.169.0 - 192.168.224 的網段,這樣致使服務啓動以後出現沒法訪問的狀況。

image.png

解決方法:上述問題的處理方式,就是手動指定 Docker 服務的啓動網段,就能夠了。

# 查看docker容器配置
$ cat /etc/docker/daemon.json
{
    "registry-mirrors": ["https://vec0xydj.mirror.aliyuncs.com"],
    "default-address-pools":[{"base":"172.17.0.0/12","size":24}],
    "experimental": true,
    "default-runtime": "nvidia",
    "live-restore": true,
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

12.Docker 服務啓動串臺


使用 docker-compose 命令各自啓動兩組服務,發現服務會串臺!

問題原由:在兩個不一樣名稱的目錄目錄下面,使用 docker-compose 來啓動服務,發現當 A 組服務啓動完畢以後,再啓動 B 組服務的時候,發現 A 組當中對應的一部分服務又從新啓動了一次,這就很是奇怪了!由於這個問題的存在會致使,A 組服務和 B 組服務沒法同時啓動。以前還覺得是工具的 Bug,後來請教了「上峯」,才知道了緣由,恍然大悟。

# 服務目錄結構以下所示
A: /data1/app/docker-compose.yml
B: /data2/app/docker-compose.yml

解決方法:發現 A 和 B 兩組服務會串臺的緣由,原來是 docker-compose 會給啓動的容器加 label 標籤,而後根據這些 label 標籤來識別和判斷對應的容器服務是由誰啓動的、誰來管理的,等等。而這裏,咱們須要關注的 label 變量是 com.docker.compose.project,其對應的值是使用啓動配置文件的目錄的最底層子目錄名稱,即上面的 app 就是對應的值。咱們能夠發現, A 和 B 兩組服務對應的值都是 app,因此啓動的時候被認爲是同一個,這就出現了上述的問題。若是須要深刻了解的話,能夠去看對應源代碼。

圖片

# 能夠將目錄結構調整爲以下所示
A: /data/app1/docker-compose.yml
B: /data/app2/docker-compose.yml
A: /data1/app-old/docker-compose.yml
B: /data2/app-new/docker-compose.yml

或者使用 docker-compose 命令提供的參數 -p 來規避該問題的發生。

# 指定項目項目名稱
$ docker-compose -f ./docker-compose.yml -p app1 up -d

13.Docker 命令調用報錯


在編寫腳本的時候經常會執行 docker 相關的命令,可是須要注意使用細節!

問題原由:CI 更新環境執行了一個腳本,可是腳本執行過程當中報錯了,以下所示。經過對應的輸出信息,能夠看到提示說正在執行的設備不是一個 tty。

圖片

隨即,查看了腳本發現報錯地方是執行了一個 exec 的 docker 命令,大體以下所示。很奇怪的是,手動執行或直接調腳本的時候,怎麼都是沒有問題的,可是等到 CI 調用的時候怎麼都是有問題。後來好好看下下面這個命令,注意到 -it 這個參數了。

# 腳本調用docker命令
docker exec -it <container_name> psql -Upostgres ......
咱們能夠一塊兒看下 exec 命令的這兩個參數,天然就差很少理解了。
-i/-interactive #即便沒有附加也保持 STDIN 打開;若是你須要執行命令則須要開啓這個選項
-t/–tty #分配一個僞終端進行執行;一個鏈接用戶的終端與容器 stdin 和 stdout 的橋樑

解決方法:docker exec 的參數 -t 是指 Allocate a pseudo-TTY 的意思,而 CI 在執行 job 的時候並非在 TTY 終端中執行,因此 -t 這個參數會報錯。

圖片

14.Docker 定時任務異常


在 Crontab 定時任務中也存在 Docker 命令執行異常的狀況!

問題原由:今天發現了一個問題,就是在備份 Mysql 數據庫的時候,使用 docker 容器進行備份,而後使用 Crontab 定時任務來觸發備份。可是發現備份的 MySQL 數據庫竟然是空的,可是手動執行對應命令切是好的,很奇怪。

# Crontab定時任務
0 */6 * * * 
    docker exec -it <container_name> sh -c 
        'exec mysqldump --all-databases -uroot -ppassword ......'

解決方法:後來發現是由於執行的 docker 命令多個 -i 致使的。由於 Crontab 命令執行的時候,並非交互式的,因此須要把這個去掉才能夠。總結就是,若是你須要回顯的話則須要 -t 選項,若是須要交互式會話則須要 -i 選項。

-i/-interactive #即便沒有附加也保持 STDIN 打開;若是你須要執行命令則須要開啓這個選項
-t/–tty  #分配一個僞終端進行執行;一個鏈接用戶的終端與容器 stdin 和 stdout 的橋樑

15.Docker 變量使用引號


compose 裏邊環境變量帶不帶引號的問題!

問題原由:使用過 compose 的同窗可能都遇到過,咱們在編寫啓動配置文件的時候,添加環境變量的時候究竟是使用單引號、雙引號仍是不使用引號。時間長了,可能咱們老是三者是同樣的,能夠相互使用。可是,直到最後咱們發現坑愈來愈多,愈來愈隱晦。

反正我是遇到過不少是由於添加引號致使的服務啓動問題,後來得出的結論就是一概不適用引號。裸奔,體驗史無前例的爽快!直到如今看到了 Github 中對應的 issus 以後,才終於破案了。

# TESTVAR="test"
在Compose中進行引用TESTVAR變量,沒法找到
# TESTVAR=test
在Compose中進行引用TESTVAR變量,能夠找到
# docker run -it --rm -e TESTVAR="test" test:latest
後來發現docker自己其實已經正確地處理了引號的使用

解決方法:獲得的結論就是,由於 Compose 解析 yaml 配置文件,發現引號也進行了解釋包裝。這就致使本來的 TESTVAR="test" 被解析成了 'TESTVAR="test"',因此咱們在引用的時候就沒法獲取到對應的值。如今解決方法就是,無論是咱們直接在配置文件添加環境變量或者使用 env_file 配置文件,能不使用引號就不適用引號。

16. Docker 刪除鏡像報錯


沒法刪除鏡像,歸根到底仍是有地方用到了!

問題原由:清理服器磁盤空間的時候,刪除某個鏡像的時候提示以下信息。提示須要強制刪除,可是發現及時執行了強制刪除依舊沒有效果。

# 刪除鏡像
$ docker rmi 3ccxxxx2e862
Error response from daemon: conflict: unable to delete 3ccxxxx2e862 (cannot be forced) - image has dependent child images
# 強制刪除
$ dcoker rmi -f 3ccxxxx2e862
Error response from daemon: conflict: unable to delete 3ccxxxx2e862 (cannot be forced) - image has dependent child images

解決方法:後來才發現,出現這個緣由主要是由於 TAG,即存在其餘鏡像引用了這個鏡像。這裏咱們能夠使用以下命令查看對應鏡像文件的依賴關係,而後根據對應 TAG 來刪除鏡像。

# 查詢依賴 - image_id表示鏡像名稱
$ docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=<image_id>)
# 根據TAG刪除鏡像
$ docker rmi -f c565xxxxc87f
bash
# 刪除懸空鏡像
$ docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

17.Docker 普通用戶切換


切換 Docker 啓動用戶的話,仍是須要注意下權限問題的!

問題原由:咱們都知道在 Docker 容器裏面使用 root 用戶的話,是不安全的,很容易出現越權的安全問題,因此通常狀況下,咱們都會使用普通用戶來代替 root 進行服務的啓動和管理的。今天給一個服務切換用戶的時候,發現 Nginx 服務一直沒法啓動,提示以下權限問題。由於對應的配置文件也沒有配置 var 相關的目錄,無奈 🤷‍♀ !️

# Nginx報錯信息
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2020/11/12 15:25:47 [emerg] 23#23: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)

解決方法:後來發現仍是 nginx.conf 配置文件,配置的有問題,須要將 Nginx 服務啓動時候須要的文件都配置到一個無權限的目錄,便可解決。

nginx
user  www-data;
worker_processes  1;
error_log  /data/logs/master_error.log warn;
pid        /dev/shm/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    gzip               on;
    sendfile           on;
    tcp_nopush         on;
    keepalive_timeout  65;
    client_body_temp_path  /tmp/client_body;
    fastcgi_temp_path      /tmp/fastcgi_temp;
    proxy_temp_path        /tmp/proxy_temp;
    scgi_temp_path         /tmp/scgi_temp;
    uwsgi_temp_path        /tmp/uwsgi_temp;
    include /etc/nginx/conf.d/*.conf;
}

史上最全、最詳細的Docker學習資料  推薦給你看一看。

新手學習項目

推薦給你們:推薦 11 個極易上手的 Docker 實踐項目

按期更新的Docker學習文章

相關文章
相關標籤/搜索