1. 程式人生 > 實用技巧 >Docker (一) Docker入門

Docker (一) Docker入門

Docker概述

什麼是Docker

Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙盒機制,相互之間不會有任何介面(類似 iPhone 的 app)。幾乎沒有效能開銷,可以很容易地在機器和資料中心中執行。最重要的是,他們不依賴於任何語言、框架或包裝系統。 Docker使用Google公司推出的Go語言進行開發實現,基於Linux核心的cgroup,namespace,以及AUFS類的Union FS等技術,對程序進行封裝隔離,屬於作業系統層面的虛擬化技術。由於隔離的程序獨立於宿主和其它的隔離的程序,因此也稱其為容器

Docker的基本概念

Docker 容器是資源分割和排程的基本單位,封裝整個服務的執行時環境,用於構建、釋出和執行釋出式應用的一個框架。它是一個跨平臺,可移植並且簡單易用的容器解決方案。

Docker 容器可以快速自動化地部署應用,並通過作業系統核心技術(namespaces、cgroups等)為容器提供資源隔離與安全保障。Docker 作為輕量級的虛擬化方式,實現了PaaS平臺高效部署、執行和維護。

Docker 在容器的基礎上,進行了進一步的封裝,從檔案系統、網路互聯到程序隔離等待,極大的簡化了容器的建立和維護。使得Docker技術比虛擬機器技術更為輕便,快捷。

Docker的優缺點

Docker的有缺點往往會將它與傳統的虛擬化技術進行對比,比如常見的虛擬機器。如下是虛擬機器和docker的結構圖。

優點:

1. 高效的利用系統資源

由於容器不需要進行硬體虛擬化以及執行完整的作業系統就可以啟動一個應用,所以說Docker對系統資源的利用率比較高。相比起虛擬機器技術,同一臺物理機可以啟動的應用Docker的數量是遠遠大於虛擬機器的數量的。

2. 更快速的啟動時間

傳統的虛擬機器需要啟動一個完整的作業系統,啟動起來往往需要幾分鐘,而Docker容器應用,由於直接運行於宿主機上,不需要啟動一個完整的作業系統,所以基本上可以做到秒級的啟動。大大的縮短了我們的開發,測試和部署的時間。

3. 一致的執行環境
開發過程中我們經常遇到環境一致性的問題,意思就是開發環境,測試環境和線上環境不一致,導致有些Bug並未在開發過程中沒有被發現。而Docker的映象提供了除核心外完整的執行時環境,確保了應用執行一致性,從而不會再出現再開發環境可以正常而生產環境不正常的問題。

4. 持續的交付和部署

對於開發和運維(DevOps)人員來說,最希望的是一次建立和配置,然後可以在任何環境中正常執行,無需擔心環境問題。而使用Docker可以通過定製應用映象來實現持續整合,持續交付,部署。開發人員可以通過Dockerfile來建立映象,並結合持續整合,系統持續進行整合測試,而於運維人員則可以直接在生產環境中快速部署該映象,甚至結合持續部署系統進行自動化部署。而使用Dockerfile使映象透明化,不僅僅開發團隊可以理解應用執行環境,也方便運維團隊理解應用執行所需條件,幫助更好的生產環境中部署該映象。

5. 更輕鬆的遷移

由於Docker確保了執行環境的一致性,使得應用的遷移更加容易,Docker可以在很多平臺上執行,無論是物理機,還是虛擬機器,公有云等其執行效果都是一致的。因此使用者可以很容易將一個平臺的運用遷移到其他平臺上,而不用擔心執行環境的變化導致無法正常執行的情況。

6. 更輕鬆的維護和擴充套件

Docker使用的分層儲存以及映象的技術,使得應用重複部分的複用更為容易,也使得應用的維護更新更加簡單,基於基礎映象進一步擴充套件映象也變得比較容易。此外Docker的眾多的官方映象就行Python的包一樣給我們提供了非常多的映象模板,大大的降低了應用服務的映象製作成本。

總的來說Docker和傳統的虛擬機器有以下差別:

特性 容器 虛擬機器
啟動 秒級 分鐘級
磁碟使用 一般為MB 一般為GB
效能 接近原生 弱於
系統支援量 單機支援上千個容器 一般幾十個

Docker的體系結構

Docker是一個C/S架構,即Docker客戶端是遠端控制器,可以通過TCP REST向Docker Host傳送請求,包括建立容器,執行容器,儲存容器,刪除容器等操作。Docker的服務端的Daemon對客戶端的請求進行相應的管理。隨後通過driver轉發至容器中的libcontainer執行環境。libcontainer提供不同於linux核心隔離的介面,類似名稱空間及控制組。這種架構允許許多個容器在共享同一個Linux核心的情況下完全隔離的執行。

上述組成部分說明:

Docker 映象(Images) Docker 映象是用於建立 Docker 容器的模板。
Docker 容器(Container) 容器是獨立執行的一個或一組應用。
Docker 客戶端(Client) Docker 客戶端通過命令列或其他工具使用 Docker API (https://docs.docker.com/reference/api/docker_remote_api)與Docker 的守護程序通訊。
Docker 主機(Host) 一個物理或者虛擬的機器用來執行 Docker 守護程序和容器。
Docker 倉庫(Registry) Docker 倉庫用來儲存映象,可以理解為程式碼控制中的程式碼倉庫。Docker Hub(https://hub.docker.com)提供了龐大的映象集合供使用。
Docker Machine Docker Machine 是一個簡化Docker安裝的命令列工具,通過一個簡單的命令即可在響應的平臺上安裝Docker,比如VirtualBox、Digital Ocean、Microsoft Azure。

Docker的應用場景


1. 簡化配置

這是Docker公司宣傳的 Docker 的主要使用場景。Docker 能將執行環境和配置放在程式碼中然後部署,同一個 Docker 的配置可以在不同的環境中使用,
這樣就降低了硬體要求和應用環境之間耦合度。

2. 程式碼流水線管理

程式碼從開發者的機器到最終生產環境上的部署,需要經過很多的中間環境。而每一箇中間環境都有微小的差別,Docker 給應用提供了一個從開發到上線均一致的環境,
讓程式碼的流水線變得簡單不少。

3. 提高開發效率

Docker 能提升開發者的開發效率。不同的開發環境中,Docker 都可以把兩件事做好,一是可以在開發環境、生產環境之間直接遷移,二是可以讓我們快速搭建開發環境。
開發環境的機器通常記憶體比較小,之前使用虛擬機器的時候,我們經常要為開發環境的機器加記憶體,而使用Docker可以輕易的讓幾十個伺服器在Docker中跑起來

4. 隔離應用

有很多原因會讓我們選擇在一個機器上執行不同的應用,Docker 非常適合在較低的成本下實現多種應用的隔離。

5. 整合伺服器

Docker 隔離應用的能力使得Docker可以整合多個伺服器以降低成本。由於沒有作業系統的記憶體佔用,以及能在多個例項之間共享沒有使用的記憶體,
Docker 可以比虛擬機器提供更好的伺服器整合解決方案。
通常資料中心的伺服器資源利用率只有30%,通過使用Docker 並進行有效的資源分配可以大幅度提高伺服器資源的利用率。

6. 除錯能力

Docker 提供了很多的工具,包括可以為容器設定檢查點、設定版本和檢視兩個容器之間的差別,這些特性可以幫助除錯Bug。

7. 多租戶環境

另外一個Docker 的使用場景是在多租戶的應用中,它可以避免關鍵應用的重寫。我們一個特別的關於這個場景的例子是為物聯網的應用開發一個快速、易用的多租戶環境。
這種多租戶的基本程式碼非常複雜,很難處理,重新規劃這樣一個應用不但消耗時間,也浪費金錢。 使用Docker,可以為每一個租戶的應用層的多個例項建立隔離的環境,這不僅簡單而且成本低廉,當然這一切得益於Docker環境的啟動速度和高效的diff命令。

8. 快速部署

在虛擬機器之前,購入部署新的硬體資源需要消耗幾天的時間。虛擬化技術(Virtualization)將這個時間縮短到了分鐘級別。
而Docker 通過為程序僅僅建立一個容器而無需啟動一個作業系統,再次將這個過程縮短到了秒級。這正式Google和Facebook
都看重的特性。我們可以建立銷燬Docker 容器而無需擔心重新啟動帶來的開銷。

Docker的核心概念

Docker映象

Docker映象類似於虛擬機器的映象,可以將它理解為一個只讀的模板。例如:一個映象可以包含一個基本的作業系統,裡面僅僅安裝了Nginx應用程式,我們就可以把這個映象稱之為Nginx映象。

映象是建立容器的基礎,通過版本管理和增量檔案系統,Docker提供一套十分簡單的機制建立,管理和更新現有映象。使用者也可以直接從網上下載映象然後直接使用。

Docker容器

Docker容器類似一個輕量級的沙箱,Docker利用容器執行和隔離應用。容器是映象執行起來後的一個例項。可以將容器比喻成面向物件的例項,而映象就是面向物件中的類。容器與容器之間彼此是相互隔離,互不可見的。

Docker映象倉庫

Docker映象倉庫是用來集中存放映象檔案的地方。有公有的也有私有的。

Docker安裝部署

系統準備:

Docker 對CentOS的版本:
CentOS 764-bit)
CentOS 6.564-bit)或者更高的版本
前提條件:
Docker 執行在CentOS 7 上,要求系統為64位、系統核心為3.10以上
Docker 執行在CentOS-6.5 或更高的版本的 CentOS 上,要求系統為64位、系統核心版本為2.6.32-431 或者更高版本。
[root@hd3 ~]# cat /etc/redhat-release   #檢視系統版本
CentOS Linux release 7.5.1804 (Core) 
[root@hd3 ~]# uname -a   #檢視核心版本
Linux hd3 3.10.0-862.el7.x86_64 #1 SMP Fri Apr 20 16:44:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Docker安裝

我們可以直接去阿里雲上找到快速的安裝方法:安裝連線

# step 1: 安裝必要的一些系統工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 新增軟體源資訊
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新並安裝Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 開啟Docker服務
sudo systemctl start docker

# 注意:
# 官方軟體源預設啟用了最新的軟體,您可以通過編輯軟體源的方式獲取各個版本的軟體包。例如官方並沒有將測試版本的軟體源置為可用,您可以通過以下方式開啟。同理可以開啟各種測試版本等。
# vim /etc/yum.repos.d/docker-ee.repo
#   將[docker-ce-test]下方的enabled=0修改為enabled=1
#
# 安裝指定版本的Docker-CE:
# Step 1: 查詢Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2: 安裝指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]

Docker映象加速配置

我們在下載網上映象的時候速度會很慢,所以我們需要配置一個加速節點,同樣的我們可以使用阿里雲的加速節點,配置方式如下:配置連線

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://tf2ihu8j.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

至此docker就安裝完成,docker的映象加速也完成。可以檢查一下:

[root@hd3 ~]# docker version
Client: Docker Engine - Community
 Version:           19.03.12  #客戶端版本
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        48a66213fe
 Built:             Mon Jun 22 15:46:54 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.12  # 服務端版本
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.10
  Git commit:       48a66213fe
  Built:            Mon Jun 22 15:45:28 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Docker基本使用

Docker的基本命令

[root@hd3 ~]# docker --help

Usage:    docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var 
and default context set with "docker context use") -D, --debug Enable debug mode -H, --host list Daemon socket(s) to connect to -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: # 管理命令,一般是配置容器熟悉等,如網路,儲存 builder Manage builds config Manage Docker configs container Manage containers context Manage contexts engine Manage the docker engine 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 trust Manage trust on Docker images volume Manage volumes Commands: attach Attach local standard input, output, and error streams to a running container # 從當前shell中進入一個執行的容器 build Build an image from a Dockerfile # 通過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 to files or directories on a container's filesystem #檢視docker容器的變化 events Get real time events from the server # 從docker容器中獲取實時事件 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 # kill指定的容器 load Load an image from a tar archive or STDIN # 從一個tar包中載入一個映象 login Log in to a Docker registry # 註冊或登陸一個docker源服務 logout Log out from a Docker registry # 從當前registory中退出 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 # 從docker映象源伺服器拉取指定映象或庫映象 push Push an image or a repository to a registry # 推送指定映象或者庫映象至docker源伺服器 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) # 儲存一個映象為一個tar包 search Search the Docker Hub for images # 從docker hub中查詢某個映象 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 #檢視Docker的版本 wait Block until one or more containers stop, then print their exit codes # 擷取容器停止時退出的狀態值

Docker的映象管理

搜尋映象:docker search

[root@hd3 ~]# docker search centos
NAME(名稱)                          DESCRIPTION(描述)                               STARS(下載次數)       OFFICIAL(官方)            AUTOMATED(自動化)
centos                             The official build of CentOS.                   6115                [OK]                
ansible/centos7-ansible            Ansible on Centos7                              132                                     [OK]
consol/centos-xfce-vnc             Centos container with "headless" VNC session…   118                                     [OK]
jdeathe/centos-ssh                 OpenSSH / Supervisor / EPEL/IUS/SCL Repos - …   115                                     [OK]
centos/systemd                     systemd enabled base container.                 86                                      [OK]
docker search 引數說明:
--automated=true I false:僅顯示自動建立的映象,預設為否; 
--no-trunc=true | false:輸出資訊不截斷顯示,預設為否;
-s,--stars=X:指定僅顯示評價為指定星級以上的映象,預設為 0,即輸出所有映象。
例如,搜尋所有自動建立的評價為 3+的帶 nginx 關鍵字的映象,如下所示:

[root@hd3 ~]# docker search --automated -s 3 nginx 
docker search 其它用法

獲取映象:docker pull 或 docker image pull

從官方的Docker Hub網站上拉去映象:

docker    pull    [選項]    [Docker    Registry地址]<倉庫名>:<標籤>
[root@hd3 ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
6910e5a164f7: Pull complete 
Digest: sha256:4062bbdd1bb0801b0aa38e0f83dece70fb7a5e9bce223423a68de2d8b784b43b
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest

檢視映象:docker images 或 docker image ls

[root@hd3 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              831691599b88        5 weeks ago         215MB
倉庫名 標籤 映象ID 建立時間 大小

刪除映象:docker rmi

docker    rmi    [選項]    <映象1>    [<映象2>    ...]
[root@hd3 ~]# docker rmi centos
Untagged: centos:latest
Deleted: sha256:831691599b88ad6cc2a4abbd0e89661a121aff14cfa289ad840fd3946f274f1f
Deleted: sha256:eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8

匯出映象:docker save 或 docker image save

如果要匯出映象到本地,提供給另一臺機器使用,可以使用docker save 或 docker image save 命令

[root@hd3 ~]# docker image save centos > /tmp/docker_centos.tar
[root@hd3 ~]# ll /tmp/docker_centos.tar 
-rw-r--r--. 1 root root 222584320 Jul 25 08:15 /tmp/docker_centos.tar

匯入映象:docker load 或 docker image load

[root@hd3 ~]# docker image load < /tmp/docker_centos.tar 
Loaded image: centos:latest

給映象打標籤: docker tag 原標籤 新標籤 或 docker image tag 原標籤 新標

[root@hd3 ~]# docker image ls  # 打標籤前
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              831691599b88        5 weeks ago         215MB
[root@hd3 ~]# docker image tag centos:latest centos:1.1   # 進行打標籤
[root@hd3 ~]# docker image ls  # 打標籤後
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              1.1                 831691599b88        5 weeks ago         215MB
centos              latest              831691599b88        5 weeks ago         215MB

Docker的容器管理

建立容器和啟動容器: docker create/run

建立容器有兩種方式一是隻建立不啟動,二是建立並啟動。因為docker的輕量級高,基本上docker是隨時用隨時刪。

(1)建立不啟動

docker create

[root@hd3 ~]# docker create -it centos /bin/bash  # 建立容器
0043b4f5bdafb79a479e7eee1ef0049b1d1d97c3c8961dc26f219872340c220b
[root@hd3 ~]# docker ps -a  # 檢視容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0043b4f5bdaf        centos              "/bin/bash"         7 seconds ago       Created                                 heuristic_kalam
(ID) (映象名) (命令) (建立時間) (狀態) (埠資訊) (容器名) [root@hd3
~]# docker start 0043b4f5bdaf # 根據ID啟動容器 0043b4f5bdaf [root@hd3 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0043b4f5bdaf centos "/bin/bash" 35 seconds ago Up 11 seconds heuristic_kalam [root@hd3 ~]# docker attach 0043b4f5bdaf # 根據ID進入容器 [root@0043b4f5bdaf /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@0043b4f5bdaf /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 00:35 pts/0 00:00:00 /bin/bash root 16 1 0 00:36 pts/0 00:00:00 ps -ef [root@0043b4f5bdaf /]# exit # 退出 exit

(2)建立並啟動

[root@hd3 ~]# docker run centos /bin/echo 'hello world'   # 建立容器執行後直接退出並關閉容器
hello world
[root@hd3 ~]# docker run --name mydocker -it centos /bin/bash  # 建立容器並進入容器
[root@9b53b30d9184 /]# 
[root@9b53b30d9184 /]# pwd
/
[root@9b53b30d9184 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

引數說明:

-i, --interactive 互動式
-t, --tty 分配一個偽終端
-d, --detach 執行容器到後臺
-a, --attach list 附加到執行的容器
--dns list 設定DNS伺服器
-e, --env list 設定環境變數
--env-file list 從檔案讀取環境變數
-p, --publish list 釋出容器埠到主機
-P, --publish-all 釋出容器所有EXPOSE的埠到宿主機隨機埠
-h, --hostname string 設定容器主機名
--ip string 指定容器IP,只能用於自定義網路
--link list 新增連線到另一個容器
--network 連線容器到一個網路
--mount mount 掛載宿主機分割槽到容器
-v, --volume list 掛載宿主機目錄到容器
--restart string,容器退出時重啟策略,預設no [always|on-failure]
--add-host list 新增其他主機到容器中/etc/hosts
-m,--memory 容器可以使用的最大記憶體量
--memory-swap 允許交換到磁碟的記憶體量--memory-swappiness=<0-100> 容器使用SWAP分割槽交換的百分比(0-100,預設為-1--memory-reservation 記憶體軟限制,Docker檢測主機容器爭用或記憶體不足時所啟用的軟 限制,使用此選項,值必須設定低於—memory,以使其優先
--oom-kill-disable當宿主機記憶體不足時,核心會殺死容器中的程序。建議設定了memory選項再禁用OOM。如果沒有設定,主機可能會耗盡記憶體
--cpus 限制容器可以使用多少可用的CPU資源
--cpuset-cpus 限制容器可以使用特定的CPU
--cpu-shares  此值設定為大於或小於預設1024值,以增加或減少容器的權重, 並使其可以訪問主機CPU週期的更大或更小比例

docker run/create 建立容器常用選項

docker run 建立容器時,Docker 後臺的流程是:

1. 檢查本地是否存在指定的映象,如果不存在就從遠端公有倉庫下載

2. 利用映象建立一個容器,並啟動該容器

3. 分配一個檔案系統給容器,並在只讀的映象層外面掛載一層可讀寫層

4. 從宿主主機配置的網橋介面中橋接一個虛擬介面到容器中

5. 從網橋的地址池配置一個IP地址給容器

6. 執行使用者指定的運用程式

7. 執行完畢後容器被自動終止

檢視容器: docker ps

[root@hd3 ~]# docker ps # 檢視已經啟動的容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         22 minutes ago      Up 22 minutes                           mydocker
[root@hd3 ~]# docker ps -a # 檢視所有容器
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"              22 minutes ago      Up 22 minutes                                   mydocker
863635a278d9        centos              "/bin/echo 'hello wo…"   23 minutes ago      Exited (0) 23 minutes ago                       crazy_goodall
0043b4f5bdaf        centos              "/bin/bash"              32 minutes ago      Exited (0) 31 minutes ago                       heuristic_kalam

停止容器: docker stop

除了使用docker stop來停止容器,當Docker容器中指定的應用終結時,容器也會自動終結,例如啟動一個終端容器,使用者通過exit或Ctrl+d來退出終端時,都會停止容器。

[root@hd3 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         27 minutes ago      Up 27 minutes                           mydocker
[root@hd3 ~]# docker stop mydocker  # 後面即可以是容器名也可以是容器ID
mydocker

進入容器: docker exec/attach

外面使用docker create建立容器或者使用docker run -d建立容器時,容器是在後臺執行的,如果需要進入這一個容器,docker內建的方法有exec和attach,還有一些工具也可以達到這個

效果,如nsenter。

方式一: attach

[root@hd3 ~]# docker ps -a # 檢視有哪些容器,根據狀態發現全部都已經停止
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"              33 minutes ago      Exited (0) 5 minutes ago                        mydocker
863635a278d9        centos              "/bin/echo 'hello wo…"   34 minutes ago      Exited (0) 34 minutes ago                       crazy_goodall
0043b4f5bdaf        centos              "/bin/bash"              43 minutes ago      Exited (0) 42 minutes ago                       heuristic_kalam
[root@hd3 ~]# docker start mydocker  # 啟動容器
pmydocker
[root@hd3 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         34 minutes ago      Up 5 seconds                            mydocker
[root@hd3 ~]# docker attach mydocker  # 進入容器
[root@9b53b30d9184 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

注意: 使用這種方式進入容器有兩個很大的缺點:

  1. 當我們進行退出時,容器會自動結束。

  2. 當第一個使用者進入容器後,執行一個阻塞的命令時,第二個使用者是無法進入容器的,所以儘量不要使用該方式。

方式二:exec(推薦使用)

exec方式是不會出現attach類似的問題,如下:

[root@hd3 ~]# docker start mydocker  # 啟動docker
mydocker
[root@hd3 ~]# docker exec -it mydocker /bin/bash     # 進入容器
[root@9b53b30d9184 /]# ls
bin  etc   lib      lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@9b53b30d9184 /]# exit   # 退出
exit
[root@hd3 ~]# docker ps  # 檢視,發現容器沒有退出
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         42 minutes ago      Up 36 seconds                           mydocker

方式三:nsenter工具

nsenter是啟動一個新的shell程序(預設是/bin/bash),同時會把新的程序切換和目標程序相同的名稱空間,這樣就相當於進入了容器的內部,nsenter要正常工作需要root的許可權。

[root@hd3 ~]# yum intall -y util-linux # 安裝工具
[root@hd3 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"              48 minutes ago      Up 6 minutes                                    mydocker
863635a278d9        centos              "/bin/echo 'hello wo…"   48 minutes ago      Exited (0) 48 minutes ago                       crazy_goodall
0043b4f5bdaf        centos              "/bin/bash"              58 minutes ago      Exited (0) 57 minutes ago                       heuristic_kalam

[root@hd3 ~]# 
[root@hd3 ~]# docker inspect -f "{{.State.Pid}}" mydocker # 獲取容器執行的程序ID
30380
[root@hd3 ~]# nsenter -t 30380 -m -u -i -n -p  # 根據進行ID進入容器
[root@9b53b30d9184 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@9b53b30d9184 /]# pwd
/
[root@9b53b30d9184 /]# exit
logout
[root@hd3 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         49 minutes ago      Up 8 minutes                            mydocker

由於上面兩條命令都太長,不方便,所以我們編寫一個指令碼進入,只需在指令碼後面跟容器ID或者容器名字即可:

[root@hd3 ~]# cat in_docker.sh 
#!/bin/bash
# Use nsenter to access docker

docker_in() {
    NAME_ID=$1
    PID=$(docker inspect -f "{{.State.Pid}}" $NAME_ID)
    nsenter -t $PID -m -u -i -n -p
}

docker_in $1

[root@hd3 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         56 minutes ago      Up 14 minutes                           mydocker
[root@hd3 ~]# ./in_docker.sh mydocker
[root@hd3 ~]# 
[root@hd3 ~]# vim in_docker.sh 
[root@hd3 ~]# ./in_docker.sh mydocker
[root@9b53b30d9184 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

刪除容器

可以使用docker rm 來刪除一個處於終止狀態的容器,如下:

[root@hd3 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"              59 minutes ago      Up 17 minutes                                      mydocker
863635a278d9        centos              "/bin/echo 'hello wo…"   59 minutes ago      Exited (0) 59 minutes ago                          crazy_goodall
0043b4f5bdaf        centos              "/bin/bash"              About an hour ago   Exited (0) About an hour ago                       heuristic_kalam
[root@hd3 ~]# docker rm 863635a278d9  # 刪除容器
863635a278d9
[root@hd3 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                         PORTS               NAMES
9b53b30d9184        centos              "/bin/bash"         59 minutes ago      Up 18 minutes                                      mydocker
0043b4f5bdaf        centos              "/bin/bash"         About an hour ago   Exited (0) About an hour ago                       heuristic_kalam

如果要刪除一個執行中的容器,可以新增 -f 引數。 Docker會發送 STGKILL訊號給容器,再進行刪除。

清理所有處於終止狀態的的容器(慎用

[root@hd3 ~]# docker ps -a   
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                           PORTS               NAMES
0ca1770a1fd0        centos              "/bin/bash -c 'while…"   About an hour ago   Exited (137) About an hour ago                       ecstatic_wu
4d18a48ee315        centos              "/bin/bash"              About an hour ago   Exited (0) About an hour ago                         amazing_herschel
b3918347393a        centos              "/bin/echo 'Hello Wo…"   About an hour ago   Exited (0) About an hour ago                         competent_lovelace
[root@hd3 ~]# docker rm $(docker ps -a -q)   # 獲取全部容器的ID,進行刪除 
0ca1770a1fd0
4d18a48ee315
b3918347393a
[root@hd3 ~]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@server ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

匯出和匯入容器

某些時候,需要將容器從一個系統遷移到另外一個系統,此時可以使用Docker的匯入和匯出功能。這也是Docker 自身提供的一個重要特性.

匯出容器: docker export

如果要匯出本地某個容器,可以使用 docker export 命令,匯出容器是指匯出一個已經建立的容器到一個檔案,不管此時這個容器是否處於執行狀態。export後面跟需要匯出的 容器ID 或者 容器名字 都可以

[root@hd3 ~]# docker export mydocker >docker_centos.tar  # 匯出容器
[root@hd3 ~]# ls docker_centos.tar 
docker_centos.tar

匯入容器: docker import

匯出的檔案又可以使用 docker import 命令匯入變成映象,例如

[root@hd3 ~]# cat docker_centos.tar | docker import - test/centos:7.1  # 將匯入的容器載入為映象檔案
sha256:f29fdf78e362b8bdbcc2e67ed9c4c1e54be8dba9e0351f866c68bf2a21f9af43
[root@hd3 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test/centos         7.1                 f29fdf78e362        5 seconds ago       215MB
centos              1.1                 831691599b88        5 weeks ago         215MB
centos              latest              831691599b88        5 weeks ago         215MB

Docker的資料管理

Docker容器中管理資料主要有兩種方式:

1. 資料卷(Data volumns)

2. 資料卷容器(Data volumes containers)

資料卷

資料卷是一個可供一個或多個容器使用的特殊目錄,它繞過UFS,可以提供很多有用的特性:

1. 資料卷可以在容器之間共享或重用

2. 對資料卷的修改會立馬生效

3. 對資料卷的更新,不會影響映象

4. 資料預設會一直存在,即使容器被刪除

管理卷: docker volumn:

[root@hd3 ~]# docker volume create myvolume  # 建立一個volumn
myvolume
[root@hd3 ~]# docker volume inspect myvolume  # 檢視volun的詳細資訊
[
    {
        "CreatedAt": "2020-07-25T10:13:15+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/myvolume/_data",  # 可以看到建立的volumn在宿主機的目錄
        "Name": "myvolume",
        "Options": {},
        "Scope": "local"
    }
]
[root@hd3 ~]# docker volume ls   # 檢視有哪些volumn
DRIVER              VOLUME NAME
local               6e5600ecd418b0200a632f168c297f2af817b779d51ff96a570a38405dee4e94
local               8d207d24425a6165714c19bacd29d33b8673ca22fc6d66bba8267cee508cf56a
local               32f4402df57e777e339b506b8e37e3e52c2b836c37b11d185a1b4d736eeeaf1d
local               mysql-vol
local               myvolume

建立容器時掛載一個volumn:

--mount引數:
src:資料卷名字 dst:需要掛載的目錄路徑 注意:如果沒有指定卷,則自動建立

如下例項:

[root@hd3 ~]# docker run -d -it --name myvolume --mount src=myvolume,dst=/data centos
253866f5e1a65819339f14712e2fffc36cc26ad640bc1bf36499b0d0beedfe68
[root@hd3 ~]# docker exec -it myvolume /bin/bash
[root@253866f5e1a6 /]# ls  # 可以看到有data目錄
bin  data  dev    etc  home  lib    lib64  lost+found  media  mnt  opt  proc  root    run  sbin  srv    sys  tmp  usr  var

可以在宿主機上建立檔案,然後再檢視docker容中是否存在檔案:

[root@hd3 _data]# pwd
/var/lib/docker/volumes/myvolume/_data
[root@hd3 _data]# ls
[root@hd3 _data]# 
[root@hd3 _data]# echo aaa >test.txt
[root@hd3 _data]# ls
test.txt

# 在容器中
[root@253866f5e1a6 data]# ls  # 一開始沒有
[root@253866f5e1a6 data]# 
[root@253866f5e1a6 data]# pwd  
/data
[root@253866f5e1a6 data]# ls  # 宿主機建立後有該檔案
test.txt

刪除資料卷: docker volume rm

Docker不會在容器被刪除後就自動刪除資料卷,而且如果我們要刪除資料卷的話,就必須先將資料卷的容器停止,刪除後,才能刪除資料卷.

[root@wallace ~]# docker rm -f myvolume
myvolume
[root@wallace ~]# docker volume rm myvolume
myvolume

掛載主機目錄作為資料卷

使用-v引數也可以指定掛載一個本地主機的目錄到容器中

[root@wallace ~]# docker run -d -it --name web -v /webapp:/opt/webapp centos # 建立一個名字叫web的容器,並將宿主機的/webapp目錄 掛載到容器的/opt/webapp
64b8d2c90226f0fda4802d4a846bd6acb1d4643d0b0632f7478d013a7a200a44
[root@wallace ~]# cd /webapp/
[root@wallace webapp]# echo "hellow" >> /webapp/index.html  # 宿主機追加檔案
[root@wallace webapp]# docker exec -it web /bin/bash
[root@64b8d2c90226 /]# cat /opt/webapp/index.html   # 進入容器檢視檔案
hellow

掛載一個宿主檔案作為資料卷

-v引數也可以從主機掛載單個檔案到容器中

[root@wallace ~]# docker run --rm -it -v ~/wallace.log:/wallace.log centos /bin/bash # 建立一個容器,並將宿主基地wallace.log檔案掛在到容器中,
--rm表示容器退出就刪除

資料卷容器

如果有一個持續更新的資料需要在容器之間共享,最好的方法是建立一個數據卷容器.資料卷容器其實就是一個正常的容器,專門用來提供資料卷供其他容器掛載.

[root@wallace ~]# docker run -d -v /dbdata --name dbdata centos  # 建立一個名為dbdata的資料卷容器, 在容器的目錄是dbdata
2669e77f93f62ccb5018ac4563008ee29d1a7a6ac39c8bdbcb3fbfa8c1d1559a
[root@wallace ~]# 
[root@wallace ~]# docker ps -a  # 注意建立的資料卷容器是無需啟動的
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
2669e77f93f6        centos              "/bin/bash"         54 seconds ago      Exited (0) 53 seconds ago                       dbdata
64b8d2c90226        centos              "/bin/bash"         17 minutes ago      Up 17 minutes                                   web
dc78600663be        centos              "/bin/bash"         39 minutes ago      Up 38 minutes                                   mycentos
[root@wallace ~]# docker run -d -it --volumes-from dbdata --name db1 centos  # 建立一個db1容器,將dbdata資料卷掛載到db1中
26fb95b8ecb7051ad91210d6f5331a4e8fa16efdad5522bd455408da27815153
[root@wallace ~]# docker exec -it db1 /bin/bash  # 進入容器
[root@26fb95b8ecb7 /]# ls  # 檢視可以發現可以遭到dbdata目錄
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@26fb95b8ecb7 /]# touch  dbdata/file1  # 在目錄中建立一個檔案,然後退出
[root@26fb95b8ecb7 /]# exit  
exit
[root@wallace ~]# docker run -d -it --volumes-from dbdata --name db2 centos # 建立一個db2容器,將dbdata資料卷掛載的到db2中
15746e015dc10a9cd58644d783277772e016a9dfc9b2559abc1e8391d108cdd1
[root@wallace ~]# docker exec -it db2 /bin/bash   # 進入db2容器
[root@15746e015dc1 /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@15746e015dc1 /]# ls dbdata/file1   # 檢視發現可以找到db1建立的容器,說明資料共享完成
dbdata/file1
[root@15746e015dc1 /]# exit
exit

從上面可以看出可以使用超過一個 --volumes-from 引數來指定從多個容器掛載不同的資料卷,也可以從其他已經掛載了資料卷的容器來級聯掛載資料卷,示例:

[root@wallace ~]# docker run -d -it --name db3 --volumes-from db1 centos # 將db1的資料卷掛載到新建立的db3容器中
c65346d5f8c23d6d5305ab6b4a5aa9cb5255778c83e4a9a66e44921329ed0dab
[root@wallace ~]# 
[root@wallace ~]# docker exec -it db3 /bin/bash  # 進入db3容器,發現可以查詢到資料
[root@c65346d5f8c2 /]# ls /dbdata/file1 
/dbdata/file1

注意:使用 --volumes-from 引數所掛載資料卷的容器自己不需要保持在執行狀態。如果刪除了掛載的容器(包括dbdata、db1和db2),資料卷也不會被自動刪除。如果要刪除一個數據卷,必須在刪除最後一個還掛載著它的容器時使用 docker rm -v 命令來指定同時刪除關聯的容器。