1. 程式人生 > 實用技巧 >-linux-Docker從入門到禿頂

-linux-Docker從入門到禿頂

Docker 是一個開源專案,誕生於 2013 年初,最初是 dotCloud 公司內部的一個業餘專案。它基於 Google 公司推出的 Go 語言實現。 專案後來加入了 Linux 基金會,遵從了 Apache 2.0 協議,專案程式碼在 GitHub 上 進行維護。Docker 自開源後受到廣泛的關注和討論,以至於 dotCloud 公司後來都改名為 Docker Inc。Redhat 已經在其 RHEL6.5 中集中支援 Docker;Google 也在其 PaaS 產品中廣泛應用。Docker 專案的目標是實現 輕量級的作業系統虛擬化解決方案。 Docker 的基礎是 Linux 容器(LXC)等技術。在 LXC 的基礎上 Docker 進行了進一步的封裝,讓使用者不需要去關心容器的管理,使得操作更為簡便。使用者操作 Docker 的容器就像操 作一個快速輕量級的虛擬機器一樣簡單。Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植 的容器中,然後釋出到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不 會有任何介面(類似 iPhone 的 app),更重要的是容器效能開銷極低。

一 為什麼要使用Docker

1 Docker容器虛擬化的好處

在雲時代,開發者建立的應用必須要能很方便地在網路上傳播,也就是說應用必須脫離底層物理硬體的限制;同時必須滿足“任何時間任何地點”可獲取可使用的特點。因此,開發者們需要一種新型的建立分散式應用程式 的方式,快速分發部署,而這正是 Docker 所能夠提供的最大優勢。Docker 提供了一種更為聰明的方式,通過 容器來打包應用、解耦應用和執行平臺。這意味著遷移的時候,只需要在新的伺服器上啟動需要的容器就可以了, 無論新舊伺服器是否是同一類別的平臺。這無疑幫助我們節約了大量的寶貴時間,並降低部署過程出現問題的風險。

2 Docker在開發和運維中的優勢

對於開發和運維人員來說,最夢寐以求的效果可能就是一次建立和配置,之後可以在任意地方、任意時間讓 應用正常執行,而 Docker 恰恰可以實現這一中級目標。具體來說,在開發和運維過程中,Docker 具有以下幾 個方面的優勢:

  • 更快的交付和部署:使用 Docker,開發人員可以使用映象來快速構建一套標準的開發環境;開發完之 後,測試和運維人員可以直接使用完全相同的環境來部署程式碼。只要是開發測試過的程式碼,就可以確保 在生產環境無縫執行。Docker 可以快速建立和刪除容器,實現快速迭代,節約開發、測試及部署的時間。
  • 更高效的利用資源:執行 Docker 容器不需要額外的虛擬化管理程式的支援,Docker 是核心級的虛擬化,可以實現更高的效能,同時對資源的額外需求很低,與傳統的虛擬機器方式相比,Docker 的效能要提高 1 ~ 2 個數量級。
  • 更輕鬆的遷移和擴充套件:Docker 容器幾乎可以在任意的平臺上執行,包括物理機、虛擬機器、公有云、私有云、個人電腦等等,同時支援主流的作業系統發行版本。這種相容效能讓使用者可以在不同的平臺之間輕鬆的遷移應用。
  • 更輕鬆的管理和更新:使用 Dockerfile,只需要小小的配置修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分發和更新,從而實現自動化並且高效的容器管理。

3 Docker與虛擬機器的比較

作為一種輕量級的虛擬化方式,Docker 在執行應用上跟傳統的虛擬機器的方式相比具有如下顯著優勢:

  • Docker 容器啟動很快,啟動和停止可以實現秒級,相比傳統的虛擬機器方式(分鐘級)要快速很多。
  • Docker 容器對系統資源需求很少,一臺主機上可以同時執行數千個 Docker 容器。
  • Docker 通過類似 git 設計理念的操作來方便使用者獲取、分發和更新應用映象,儲存複用,增量更新。
  • Docker 通過 Dockerfile 支援靈活的自動化建立和部署機制,可以提高工作效率,並標準化流程。
特性 容器 虛擬機器
啟動速度 秒級 分鐘級
效能 接近原生 較好
記憶體 MB級 GB級
硬碟適應 MB級 GB級
執行密度 單臺主機支援上千個 單臺主機支援幾個
隔離性 安全隔離 完全隔離
遷移 優秀 一般

二 Docker與虛擬化

Docker 以及其他容器技術,都屬於作業系統虛擬化範疇,作業系統細膩化最大的特點就是不需要額外的 supervisor 支援。Docker 虛擬化方式之所以有眾多優勢,跟作業系統虛擬化技術自身的設計和實現分不開。

傳統方式是在硬體層面實現虛擬化,需要有額外的虛擬機器管理應用和虛擬機器作業系統層。Docker 容器時在 作業系統層面實現虛擬化,直接複用本地主機的作業系統,因此更加輕量級。

三 Docker概念和使用

Docker 中有三個核心概念:映象、容器和倉庫。因此,準確把握這三大概念對於掌握 Docker 技術尤為重要。

  1. 映象(Image)

Docker 映象(Image),就相當於是一個 root 檔案系統。比如官方映象 ubuntu:16.04 就包含了完

整的一套 Ubuntu16.04 最小系統的 root 檔案系統。

  1. 容器(Container)

映象(Image)和容器(Container)的關係,就像是面向物件程式設計中的類和例項一樣,映象是靜態的定義,容器是映象執行時的實體。容器可以被建立、啟動、停止、刪除、暫停等。

  1. 倉庫(Repository)

用來儲存映象的倉庫。當我們構建好自己的映象之後,需要存放在倉庫中,當我們需要啟動一個映象時, 可 以在倉庫中下載下來。

1 使用Docker映象

​ docker 映象是 docker 中三大概念之一,其主要作用是作為啟動容器的模板。

1)獲取映象

映象是執行容器的模板,官方 Docker Hub 倉庫已經提供了許多映象共開發者使用。如果我們需要獲取某 個映象則可以去 docker 倉庫下載所需的映象。

下載映象的格式:docker pull image_name:image_version

下載映象例項:

[root@arther-linux ~]# docker pull nginx:1.17
Trying to pull repository docker.io/library/nginx ... 
1.17: Pulling from docker.io/library/nginx
afb6ec6fdc1c: Pull complete 
b90c53a0b692: Pull complete 
11fa52a0fdc0: Pull complete 
Digest: sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a6420d8ae16ef37c92d1eb26699
Status: Downloaded newer image for docker.io/nginx:1.17

下載的時候,我們可以看到有若干層組成,像 afb6ec6fdc1c 這樣的字串是層的唯一 ID(實際上,完整的 ID 包括 256 位元, 64 個十六進位制字元組成)。使用 docker pull 命令下載中會獲取並輸出映象的各層資訊。當不 同的映象包括相同的層的時候,本地僅存一份內容,減小儲存空間。

2)檢視映象資訊

​ 映象主要包括映象檔案、映象tag以及映象詳細資訊等等。

映象列表

使用兩條命令

​ docker images 或 docker image ls

可以列舉本地主機上已有映象的基本資訊

[root@arther-linux ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              74d107221092        13 days ago         104 MB
myredis             latest              74d107221092        13 days ago         104 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/nginx     1.17                9beeba249f3e        6 months ago        127 MB

列舉資訊,可以看到幾個欄位資訊:

  • 映象來源:來自哪個倉庫,預設來自:hub.docker.com
  • 映象標籤:比如1.17、latest
  • 映象ID:例如9beeba249f3e
  • 映象建立時間:例如 6 months ago
  • 映象大小:127 MB

映象大小資訊只是表示了該映象的邏輯體積大小,實際上由於相同的映象層本地只會儲存一份,物理上佔用

的儲存空間會小於各映象邏輯體積之和。

image子命令主要支援如下選項:

  • -a:列出所有(包括臨時檔案)映象檔案
[root@arther-linux ~]# docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              74d107221092        13 days ago         104 MB
myredis             latest              74d107221092        13 days ago         104 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/nginx     1.17                9beeba249f3e        6 months ago        127 MB

  • --digests=true|false:列出映象的數字摘要值
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              74d107221092        13 days ago         104 MB
myredis             latest              74d107221092        13 days ago         104 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/nginx     1.17                9beeba249f3e        6 months ago        127 MB
[root@arther-linux ~]# docker images --digests
REPOSITORY          TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
docker.io/redis     latest              <none>                                                                    74d107221092        13 days ago         104 MB
myredis             latest              <none>                                                                    74d107221092        13 days ago         104 MB
docker.io/nginx     1.19.2              sha256:c628b67d21744fce822d22fdcc0389f6bd763daac23a6b77147d0712ea7102d0   7e4d58f0e5f3        2 months ago        133 MB
docker.io/nginx     1.17                sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a6420d8ae16ef37c92d1eb26699   9beeba249f3e        6 months ago        127 MB
  • -q:僅顯示ID資訊
[root@arther-linux ~]# docker images -q
74d107221092
74d107221092
7e4d58f0e5f3
9beeba249f3e
為映象新增tag

為了方便後續工作使用特定的映象,還可以使用docker tag命令來為本地的映象新增標籤。

[root@arther-linux ~]# docker tag redis:latest myredis:latest
[root@arther-linux ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              74d107221092        13 days ago         104 MB
myredis             latest              74d107221092        13 days ago         104 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/nginx     1.17                9beeba249f3e        6 months ago        127 MB
使用inspect命令來檢視詳細資訊

使用docker inspect 命令來獲取映象的詳細資訊,包括PID、作者、架構等等。

[root@arther-linux ~]# docker inspect redis
[
    {
        "Id": "sha256:74d107221092875724ddb06821416295773bee553bbaf8d888ababe9be7b947f",
        "RepoTags": [
            "docker.io/redis:latest",
            "myredis:latest"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "",
        "Created": "2020-11-18T08:28:42.383873008Z",
        "Container": "1a904a9885d0bdcb73bbb4899df9632a1f89a75c6bee47c55981e4834124c3cf",
        "ContainerConfig": {
            "Hostname": "1a904a9885d0",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
					...
使用history命令來檢視映象歷史
[root@arther-linux ~]# docker history redis
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
74d107221092        13 days ago         /bin/sh -c #(nop)  CMD ["redis-server"]         0 B                 
<missing>           13 days ago         /bin/sh -c #(nop)  EXPOSE 6379                  0 B                 
<missing>           13 days ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-ent...   0 B                 
<missing>           13 days ago         /bin/sh -c #(nop) COPY file:df205a0ef6e6df...   374 B               
<missing>           13 days ago         /bin/sh -c #(nop) WORKDIR /data                 0 B                 
<missing>           13 days ago         /bin/sh -c #(nop)  VOLUME [/data]               0 B                 
<missing>           13 days ago         /bin/sh -c mkdir /data && chown redis:redi...   0 B                 
<missing>           13 days ago         /bin/sh -c set -eux;   savedAptMark="$(apt...   30.5 MB             
<missing>           13 days ago         /bin/sh -c #(nop)  ENV REDIS_DOWNLOAD_SHA=...   0 B                 
<missing>           13 days ago         /bin/sh -c #(nop)  ENV REDIS_DOWNLOAD_URL=...   0 B                 
<missing>           13 days ago         /bin/sh -c #(nop)  ENV REDIS_VERSION=6.0.9      0 B                 
<missing>           13 days ago         /bin/sh -c set -eux;  savedAptMark="$(apt-...   4.15 MB             
<missing>           13 days ago         /bin/sh -c #(nop)  ENV GOSU_VERSION=1.12        0 B                 
<missing>           13 days ago         /bin/sh -c groupadd -r -g 999 redis && use...   329 kB              
<missing>           13 days ago         /bin/sh -c #(nop)  CMD ["bash"]                 0 B                 
<missing>           13 days ago         /bin/sh -c #(nop) ADD file:d2abb0e4e7ac177...   69.2 MB      

注意:有些構建資訊過長,可以使用--no-trunc 選項來輸出完整資訊。

搜尋映象

在docker中搜索映象主要使用Search子命令,預設只搜尋Docker Hub官方映象倉庫中的映象。其語法為

docker search [option] keyword

支援的命令選項主要包括:

  • -f:過濾輸出內容
# 搜尋官方提供的帶有Redis關鍵字的映象
[root@arther-linux ~]# docker search -f is-official=true redis
INDEX       NAME              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/redis   Redis is an open source key-value store th...   8792  

[OK] 

# 搜尋被收藏超過 8000 個的並且關鍵詞包括 Redis 的映象
[root@arther-linux ~]# docker search -f stars=8000 redis
INDEX       NAME              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/redis   Redis is an open source key-value store th...   8792      [OK]    
  • --limit:限制輸出結果
[root@arther-linux ~]# docker search -f stars=8 --limit 3 redis
INDEX       NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/redis                            Redis is an open source key-value store th...   8792      [OK]       
docker.io   docker.io/bitnami/redis                    Bitnami Redis Docker Image                      168                  [OK]
docker.io   docker.io/rediscommander/redis-commander   Alpine image for redis-commander - Redis m...   47                   
  • --no-trunc:不截斷輸出結果
[root@arther-linux ~]# docker search -f stars=8 --no-trunc redis
INDEX       NAME                                       DESCRIPTION                                                                            STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/redis                            Redis is an open source key-value store that functions as a data structure server.     8792      [OK]       
docker.io   docker.io/bitnami/redis                    Bitnami Redis Docker Image                                                             168                  [OK]
docker.io   docker.io/sameersbn/redis                                                                                                         82                   [OK]
docker.io   docker.io/grokzen/redis-cluster            Redis cluster 3.0, 3.2, 4.0, 5.0, 6.0                                                  72                   
docker.io   docker.io/rediscommander/redis-commander   Alpine image for redis-commander - Redis management tool.                              47                   [OK]
docker.io   docker.io/kubeguide/redis-master           redis-master with "Hello World!"                                                       33                   
docker.io   docker.io/redislabs/redisearch             Redis With the RedisSearch module pre-loaded. See http://redisearch.io                 29                   
docker.io   docker.io/redislabs/redis                  Clustered in-memory database engine compatible with open source Redis by Redis Labs    27                   
docker.io   docker.io/arm32v7/redis                    Redis is an open source key-value store that functions as a data structure server.     22                   
docker.io   docker.io/oliver006/redis_exporter          Prometheus Exporter for Redis Metrics. Supports Redis 2.x, 3.x, 4.x and 5.x
輸出引數釋義
  • NAME:盡享倉庫源的名稱
  • DESCRIPTION:映象的描述
  • OFFICIAL:是否docker官方釋出
  • stars:類似 Github 裡面的 star,表示點贊、喜歡的意思。
  • AUTOMATED: 自動構建。

3) 刪除和清理映象

在 docker 中,刪除映象主要使用 rmi 子命令,清理映象主要使用 prune 子命令。

使用標籤刪除映象
[root@arther-linux ~]# docker rmi myredis
Untagged: myredis:latest
[root@arther-linux ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/redis     latest              74d107221092        13 days ago         104 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/nginx     1.17                9beeba249f3e        6 months ago        127 MB

如果根據IMAGE ID 刪除映象,那麼redis也會被刪除,因為myredis與redis引用的是同一個IMAGE ID,只是打上的標籤不同,myredis是我們自定義的標籤。

引數:

​ -f: 強制刪除映象

[root@arther-linux ~]# docker rmi -f redis
Untagged: redis:latest
Deleted: sha256:74d107221092875724ddb06821416295773bee553bbaf8d888ababe9be7b947f
Deleted: sha256:d951b383737320b4e1ac7f9bb63f3919bcf25363ccb59fbb52a41e45ba70ffdd
Deleted: sha256:d3b2581a1c92973ee9a41fc00e5628047ce7e644a66240fb859b38831bd525b4
Deleted: sha256:a447231da503a58432b4d7409980139206fdf398fbde189d8a7229dd0663f472
Deleted: sha256:f786204ca260bcaef3d47ecad10821878028239072c65ceb2a1f212f275f9367
Deleted: sha256:b68afce5f52461f79be59806be00e43ea95152a0358b8dc5de9ac3f486a70d7e
Deleted: sha256:f5600c6330da7bb112776ba067a32a9c20842d6ecc8ee3289f1a713b644092f8
清理映象

使用一段時間之後,docker 會產生很多臨時檔案,以及一些沒有被使用的映象,我們可以通過 docker image prune 命令來進行清理。

引數:

​ -a: 刪除所有無用的映象不光是臨時映象

[root@arther-linux ~]# docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: docker.io/nginx:1.17
untagged: docker.io/nginx@sha256:6fff55753e3b34e36e24e37039ee9eae1fe38a6420d8ae16ef37c92d1eb26699
deleted: sha256:9beeba249f3ee158d3e495a6ac25c5667ae2de8a43ac2a8bfd2bf687a58c06c9
deleted: sha256:8fb6373b4cca3383756d7fd7843dd92f95827e5f2913609e09a9621dcddb3752
deleted: sha256:8b09841626797a03a9fe5e73aa38aeacf9ff0ce85a3004236ff35234eec3b35c
deleted: sha256:ffc9b21953f4cd7956cdf532a5db04ff0a2daa7475ad796f1bad58cfbaf77a07
untagged: docker.io/redis:latest
untagged: docker.io/redis@sha256:5b98e32b58cdbf9f6b6f77072c4915d5ebec43912114031f37fa5fa25b032489
deleted: sha256:74d107221092875724ddb06821416295773bee553bbaf8d888ababe9be7b947f
deleted: sha256:d951b383737320b4e1ac7f9bb63f3919bcf25363ccb59fbb52a41e45ba70ffdd
deleted: sha256:d3b2581a1c92973ee9a41fc00e5628047ce7e644a66240fb859b38831bd525b4
deleted: sha256:a447231da503a58432b4d7409980139206fdf398fbde189d8a7229dd0663f472
deleted: sha256:f786204ca260bcaef3d47ecad10821878028239072c65ceb2a1f212f275f9367
deleted: sha256:b68afce5f52461f79be59806be00e43ea95152a0358b8dc5de9ac3f486a70d7e
deleted: sha256:f5600c6330da7bb112776ba067a32a9c20842d6ecc8ee3289f1a713b644092f8

Total reclaimed space: 231 MB
  
[root@arther-linux ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB

​ -f : 強制刪除映象,而不進行提示。

[root@arther-linux ~]# docker image prune -a -f
Deleted Images:
untagged: docker.io/redis:latest
untagged: docker.io/redis@sha256:5b98e32b58cdbf9f6b6f77072c4915d5ebec43912114031f37fa5fa25b032489
deleted: sha256:74d107221092875724ddb06821416295773bee553bbaf8d888ababe9be7b947f
deleted: sha256:d951b383737320b4e1ac7f9bb63f3919bcf25363ccb59fbb52a41e45ba70ffdd
deleted: sha256:d3b2581a1c92973ee9a41fc00e5628047ce7e644a66240fb859b38831bd525b4
deleted: sha256:a447231da503a58432b4d7409980139206fdf398fbde189d8a7229dd0663f472
deleted: sha256:f786204ca260bcaef3d47ecad10821878028239072c65ceb2a1f212f275f9367
deleted: sha256:b68afce5f52461f79be59806be00e43ea95152a0358b8dc5de9ac3f486a70d7e
deleted: sha256:f5600c6330da7bb112776ba067a32a9c20842d6ecc8ee3289f1a713b644092f8

4)構建映象

​ 構建映象一般有三種情況,基於容器匯入、基於本地模板匯入、基於Dockerfile建立。

基於容器儲存

主要格式:docker container_id commit

主要引數:

  • -a 作者資訊
  • -m 提交資訊
  • -p 提交時,暫停容器執行

啟動一個容器、修改並儲存

# 啟動容器 -d:後臺啟動     
[root@arther-linux ~]# docker run -d -it centos /bin/bash
Unable to find image 'centos:latest' locally
Trying to pull repository docker.io/library/centos ... 
latest: Pulling from docker.io/library/centos
3c72a8ed6814: Pull complete 
Digest: sha256:76d24f3ba3317fa945743bb3746fbaf3a0b752f10b10376960de01da70685fbd
Status: Downloaded newer image for docker.io/centos:latest
50177d1cafb40134f64faa9c20e1bd6097bcbc8f23a9a869f1c6ee8568376721

# 將django目錄下的檔案掛載到容器html檔案下
# 沒有許可權,需要再加引數,有許可權操作html檔案
[root@arther-linux django]# docker run -d -v /test/django/:/usr/share/nginx/html --privileged=true -P nginx:1.19.5 
3ead75a41602d0366316688891997d5f77b478d050971d2eb58befc11590c92c

# 檢視執行的容器
root@arther-linux ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
50177d1cafb4        centos              "/bin/bash"         13 minutes ago      Up 13 minutes                           relaxed_visvesvaraya

# 進入到該容器中
[root@arther-linux ~]# docker exec  relaxed_visvesvaraya touch test

# 在此容器中新增映象檔案
[root@arther-linux ~]# docker commit -m "Add a file" -a "Alvin" relaxed_visvesvaraya
sha256:c4cb6a13ea8003039d2745d90e72a3515fb4f72e5deeda800e3afc418a875160
  
# 再次檢視映象,多了一個映象檔案
[root@arther-linux ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              c4cb6a13ea80        36 seconds ago      215 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/centos    latest              0d120b6ccaa8        3 months ago        215 MB

5)儲存映象

有時我們需要將一臺電腦上的映象複製到另一臺電腦上使用,除了可以藉助倉庫外,還可以直接將映象儲存成一個檔案,再拷貝到另一臺電腦上匯入使用。

對於映象的匯出和匯入,Docker提供了兩種方案。

使用export和import 匯出和匯入

export 和 import 的針對點是容器,將本機的容器匯出為映象包。(所以只能操作一個映象)

使用export儲存容器為映象

# 儲存該容器為映象並重定向覆蓋到nginx.tar,相當於複製一份,沒有對原容器進行剪下
[root@arther-linux ~]# docker export relaxed_visvesvaraya>nginx.tar

# 在當前操作的目錄下儲存
[root@arther-linux ~]# ll
總用量 217180
-rw-------. 1 root root      3108 11月 19 16:42 anaconda-ks.cfg
-rw-r--r--. 1 root root 222377984 12月  1 18:56 nginx.tar
-rw-------. 1 root root      2392 11月 19 16:42 original-ks.cfg
 
# 將該容器匯出為主機的映象檔案,並沒有影響該容器的執行,所以只是相當於複製操作。
[root@arther-linux test]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
50177d1cafb4        centos              "/bin/bash"         38 minutes ago      Up 38 minutes                           relaxed_visvesvaraya

使用import匯入包為映象

# 將主機的映象檔案匯入為docker中的映象
[root@arther-linux test]# docker import nginx.tar nginx:v1
sha256:134f27a95ff8860656bca73313e0fb7a70c39b9465adbd366d63b5a81207666e
[root@arther-linux test]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v1                  134f27a95ff8        25 seconds ago      215 MB
<none>              <none>              c4cb6a13ea80        21 minutes ago      215 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/centos    latest              0d120b6ccaa8        3 months ago        215 MB

使用save和load 匯出和匯入

save 和 load 的針對的點是映象,將本機的映象匯入、匯出為映象包。(所以可以操作多個映象)

使用save儲存映象

# 將docker中的映象檔案匯出重定向到主機的test目錄下
[root@arther-linux test]# docker save docker.io/nginx >busybox.tar
[root@arther-linux test]# ll
總用量 350808
-rw-rw-r--. 1 bibibi user10         0 11月 25 20:28 1.txt
-rw-r--r--. 1 root   user10 136842752 12月  1 19:51 busybox.tar

使用save儲存多個映象

[root@arther-linux test]# docker save -o test.tar docker.io/nginx:1.19.2 docker.io/centos:latest 
[root@arther-linux test]# ll
總用量 701596
-rw-rw-r--. 1 bibibi user10         0 11月 25 20:28 1.txt
-rw-------. 1 root   user10 359206400 12月  1 19:58 test.tar
  
# 匯入驗證是否有兩個映象
[root@arther-linux test]# docker load <test.tar
Loaded image: docker.io/centos:latest
Loaded image: docker.io/nginx:1.19.2
    
# 由於已存在該映象,所以不會重複
[root@arther-linux ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v1                  134f27a95ff8        About an hour ago   215 MB
<none>              <none>              c4cb6a13ea80        About an hour ago   215 MB
docker.io/nginx     1.19.2              7e4d58f0e5f3        2 months ago        133 MB
docker.io/centos    latest              0d120b6ccaa8        3 months ago        215 MB

使用load匯入映象

[root@arther-linux test]# docker load <test.tar
Loaded image: docker.io/centos:latest
Loaded image: docker.io/nginx:1.19.2
兩種方案的差別
  • 檔案大小不同

    • export 匯出的映象檔案體積小於 save 儲存的映象,因為export僅儲存映象且只儲存一個映象,save相對儲存的資訊較為完整且能儲存多個映象。
  • 是否可以對映象重新命名

    • docker import 可以為映象指定新名稱,docker load 不能對載入的映象重新命名。
  • 是否可以同時將多個映象打包到一個檔案中

    • docker export 不支援,docker save 支援。
  • 是否包含映象歷史

    • export 匯出(import 匯入)是根據容器拿到的映象,再匯入時會丟失映象所有的歷史記錄和元資料資訊(即僅儲存容器當時的快照狀態),所以無法進行回滾操作。

      save 儲存(load 載入)的映象,沒有丟失映象的歷史,可以回滾到之前的層(layer)。

  • 應用場景不同

    • docker export 的應用場景:主要用來製作基礎映象,比如我們從一個 ubuntu 映象啟動一個容器,然後安裝一些軟體和進行一些設定後,使用 docker export 儲存為一個基礎映象。然後,把這個映象分發給其他人使用,比如作為基礎的開發環境。
    • docker save 的應用場景:如果我們的應用是使用 docker-compose.yml 編排的多個映象組合,但我們要部署的客戶伺服器並不能連外網。這時就可以使用 docker save 將用到的映象打個包,然後拷貝到客戶伺服器上使用 docker load 載入。

3 使用Docker容器

1)建立容器

在Docker中,真正對外提供服務的還是容器。

建立容器的格式:docker run [option] image [cmd]

# 80是容器預設的埠,對映到主機的自定義埠
[root@arther-linux ~]# docker run -d --name nginx -p 8080:80 nginx
Unable to find image 'nginx:latest' locally
Trying to pull repository docker.io/library/nginx ... 
latest: Pulling from docker.io/library/nginx
852e50cd189d: Pull complete 
571d7e852307: Pull complete 
addb10abd9cb: Pull complete 
d20aa7ccdb77: Pull complete 
8b03f1e11359: Pull complete 
Digest: sha256:6b1daa9462046581ac15be20277a7c75476283f969cb3a61c8725ec38d3b01c3
Status: Downloaded newer image for docker.io/nginx:latest
dac679815977e6132bad3d6471c158241cb3c16769e1140f84bbc229078f8e49

# 此時可以通過瀏覽器進行訪問
http://10.211.55.3:8080/

容器啟動引數

啟動引數 意義
-d 以守護程序方式執行
-p 指定對映埠
-P 隨機對映埠
-i 保持標準輸入開啟
-t 分配一個偽終端
-v 設定掛載檔案到主機上
--privileged 掛載檔案的許可權,為True則是有該許可權
--rm 當容器關閉時自動刪除
--name 為啟動的容器設定一個名字
--network 指定使用哪個網路
-e 設定容器中的環境變數
--link 連線到另一個容器
-h 指定容器內的主機名

2)停止容器

docker 終止容器是首先向容器傳送 SIGTERM 訊號,等待一段時間超時後(預設 10 秒),再發送 SIGKILL 訊號 來終止容器。

[root@arther-linux ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
dac679815977        nginx               "/docker-entrypoin..."   5 minutes ago       Up About a minute   0.0.0.0:8080->80/tcp   nginx
[root@arther-linux ~]# docker stop nginx
nginx

[root@arther-linux ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

# 沒有執行的容器了

# 該容器停止執行,不能訪問
# 再重啟時,不需要docker run 的命令

[root@arther-linux ~]# docker start nginx 
nginx
[root@arther-linux ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
dac679815977        nginx               "/docker-entrypoin..."   11 minutes ago      Up 30 seconds       0.0.0.0:8080->80/tcp   nginx

3)進入容器

在使用容器的過程中,我們難免需要進入容器進行排查問題。

attach

attach 是最早 docker 官方推出的進入容器的命令了,不過使用該命令有一個問題。當多個視窗同時使用該命令 進入該容器時,所有的視窗都會同步顯示。如果有一個視窗阻塞了,那麼其他視窗也無法再進行操作,當所有窗 口退出時,容器結束。

exec

既 attach 之後,exec 是官方推出的有一個新的進入容器的命令,這個命令相當於在容器中執行一個命令。

[root@arther-linux ~]# docker exec -it nginx /bin/bash
root@dac679815977:/# 
nsenter

需要配合 docker inspect 來使用(早期沒有 exec 命令時,企業當中最長用的方式之一),Docker 是用 golang 語言開發,所以它也支援 go 語言的摸版語法。

[root@instance-gvpb80ao docs]# nsenter --target $( docker inspect -f {{.State.Pid}} nginxv1 ) --mount --uts --ipc --net --pid 
mesg: ttyname failed:: No such device 
root@6f99ae8757f7:/#
ssh

在生產環境中排除了使用 docker attach 命令進入容器之後,相信大家第一個想到的就是 ssh。在映象(或容器) 中安裝 SSH Server,這樣就能保證多人進入容器且相互之間不受干擾了,相信大家在當前的生產環境中(沒有 使用 Docker 的情況)也是這樣做的。但是使用了 Docker 容器之後不建議使用 ssh 進入到 Docker 容器內。

總結

進入 docker container 中一般情況下有 4 種方式,最常用的是 exec 和 nsenter 這兩種。

Nsenter 和 exec 之間的區別:

  • Exec 是 docker 自帶的命令,Nsenter 是 Linux 提供的命令。
  • Exec 相當於在容器內執行一個命令,而 Nsenter 是僅僅進入容器之中而已。

4)刪除容器

可以使用 docker rm 命令來刪除處於終止或退出狀態的容器,命令格式為:docker rm container。

[root@arther-linux ~]# docker rm nginx

強制刪除一個正在執行的容器

[root@arther-linux ~]# docker rm -f nginx

5)匯入與匯出容器

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

匯出容器

匯出容器是指,匯出一個已經建立的容器到一個檔案,不管此時這個容器是否處於執行狀態 可以使用 docker

[container] export 令,該命令格式為:

[root@arther-linux ~]# docker export relaxed_visvesvaraya>nginx.tar
匯入容器

匯出的檔案又可以使用 docker [ container] import 命令導人變成映象,該命令格式為:

[root@arther-linux test]# docker import nginx.tar nginx:v1
sha256:134f27a95ff8860656bca73313e0fb7a70c39b9465adbd366d63b5a81207666e
  
# 然後可以通過run命令啟動成為容器

實際上,既可以使用 docker load 命令來匯入映象儲存檔案到本地映象庫,也可以使 docker [container] import 命令來匯入一個容器快照到本地映象庫 這兩者的區別在於 容器快照檔案將丟棄所有的歷史記錄和元資料資訊 (即僅儲存容器當時的快照狀態),而映象儲存檔案將儲存完整記錄,體積更大 此外,從容器快照檔案導人時可以重新指定標籤等元資料資訊。

主要用來製作基礎映象,比如我們從一個 ubuntu 映象啟動一個容器,然後安裝一些軟體和進行一些設定後,使用 docker export 儲存為一個基礎映象。然後,把這個映象分發給其他人使用,比如作為基礎的開發環境。

檢視容器

檢視容器詳情可以使用 docker container inspect [OPTIONS] CONTAINER [CONTAINER . .. ]子命令。

[root@arther-linux ~]# docker inspect nginx
[
    {
        "Id": "dac679815977e6132bad3d6471c158241cb3c16769e1140f84bbc229078f8e49",
        "Created": "2020-12-01T12:21:49.144136711Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 18242,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-12-01T12:45:55.304273001Z",
            "FinishedAt": "2020-12-01T12:45:47.984137475Z"
        },
				......

5)容器命令詳解

複製命令

複製命令類似於 Linux 系統中的 scp 命令,是將宿主主機上的內容上傳到容器中,也可能是將容器中的檔案 下載到宿主主機中。

# 將容器中的內容複製到宿主的主機中
[root@arther-linux ~]# docker cp 746be4d00a18:/root/test.txt /

# 將宿主檔案複製到容器中
[root@arther-linux /]# docker cp a.tar.gz 520b5630ef9c:/root
   

示意圖

四 Docker網路

Docker 本身的技術依賴於 Linux 核心虛擬化技術的發展。所以 Docker 對 Linux 核心的特性有很強的依賴。

1 網路基礎

其中Docker使用到的與Linux網路有關的技術分別有:網路名稱空間、Veth、Iptables、網橋、路由。

1)網路名稱空間

​ 為了支援網路協議棧的多個例項,Linux 在網路協議棧中引入了網路名稱空間(Network Namespace),這些獨立的協議棧被隔離到不同的名稱空間中。處於不同的名稱空間的網路協議棧是完全隔離的,彼此之間無法進行網路通訊,就好像兩個“平行宇宙”。通過這種對網路資源的隔離,就能在一個宿主機上虛擬多個不同的網路環境,而 Docker 正是利用這種網路名稱空間的特性,實現了不同容器之間的網路隔離。在 Linux 的網路名稱空間內可以有自己獨立的 Iptables 來轉發、NAT 及 IP 包過濾等功能。

​ Linux 的網路協議棧是十分複雜的,為了支援獨立的協議棧,相關的這些全域性變數都必須修改為協議棧私有。最好的辦法就是讓這些全域性變數成為一個 Net Namespace 變數的成員,然後為了協議棧的函式呼叫加入一個Namespace 引數。這就是 Linux 網路名稱空間的核心。所以的網路裝置都只能屬於一個網路名稱空間。當然,通常的物理網路裝置只能關聯到 root 這個名稱空間中。虛擬網路裝置則可以被建立並關聯到一個給定的名稱空間中,而且可以在這些名稱空間之間移動。

建立一個名稱空間
[root@arther-linux /]# ip netns add test01
[root@arther-linux /]# ip netns add test02
[root@arther-linux /]# ip netns list
test02
test01
Veth裝置

引入 Veth 裝置對是為了在不同的網路名稱空間之間進行通訊,利用它可以直接將兩個網路名稱空間連結起 來。由於要連線的兩個網路名稱空間,所以 Veth 裝置是成對出現的,很像一對乙太網卡,並且中間有一根直連 的網線。既然是一對網絡卡,那麼我們將其中一端稱為另一端的 peer。在 Veth 裝置的一端傳送資料時,它會將資料直接傳送到另一端,並觸發另一端的接收操作。

但是如果需要建立多個裝置之間的關聯,如10個裝置每個都需要互相關聯,那麼就是從9開始遞迴加到1,這樣的操作及其麻煩。所以需要類似中轉站樣的裝置,能夠與所有裝置進行關聯,然後通過它進行轉發資料。

網橋

​ Linux 可以支援多個不同的網路,它們之間能夠相互通訊,就需要一個網橋。網橋是二層的虛擬網路裝置,它是把若干個網路介面“連線”起來,從而報文能夠互相轉發。網橋能夠解析收發的報文,讀取目標MAC地址的資訊,和自己記錄的MAC表結合,來決定報文的轉發目標網口。

​ 網橋裝置 brO 綁定了 eth0、 eth1 。對於網路協議械的上層來說,只看得到 brO 。因為橋接是在資料鏈 路層實現的 ,上層不需要關心橋接的細節,於是協議枝上層需要傳送的報文被送到 brO ,網橋裝置的處理程式碼判斷報文該被轉發到 ethO 還是 ethl ,或者兩者皆轉發。反過來,從 ethO 或從 ethl 接收到的報文被提交給網橋的處理程式碼,在這裡會判斷報文應該被轉發、丟棄還是提交到協議枝上層。 而有時 ethl 也可能會作為報文的源地址或目的地址 直接參與報文的傳送與接收,從而繞過網橋。

Iptables

​ 我們知道, Linux 絡協議樵非常高效,同時比較複雜 如果我們希望在資料的處理過程中對關心的資料進行一些操作該怎麼做呢? Linux 提供了一套機制來為使用者實現自定義的資料包處理過程。

​ 在 Linux 網路協議棋中有一組回撥函式掛接點,通過這些掛接點掛接的鉤子函式可以在 Linux 網路棋處理資料包的過程中對資料包進行 些操作,例如過濾、修改、丟棄等 整個掛接點技術叫作 Netfilter lptables

​ Netfilter 負責在核心中執行各種掛接的規則,執行在核心模式中:而 lptables 是在使用者模式下執行的程序,負責協助維護核心中 Netfilter 的各種規則表 通過 者的配合來實現整個 Linux 網路協議戰中靈活的資料包處理機制。

總結

裝置 作用總結
network namespace 主要提供了關於網路資源的隔離,包括網路裝置、IPv4和 IPv6 協議棧、IP 路由表、防火牆、/proc/net 目錄、/sys/class/net 目錄、埠(socket)等。
linux Bridge 功能相當於物理交換機,為連在其上的裝置(容器)轉發資料幀。如 docker0 網橋。ip
iptables 主要為容器提供NAT以及容器網路安全
veth pair 兩個虛擬網絡卡組成的資料通道。在 Docker 中,用於連線 Docker 容器和 Linux ,Bridge一端在容器中作為 eth0 網絡卡,另一端在 Linux Bridge 中作為網橋的一個埠。

2)Docker 網路模式

​ Docker使用Linux橋接的方式,在宿主機虛擬一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為 Container-IP,同時 Docker 網橋是每個容器的預設閘道器。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的 Container-IP 直接通訊。

​ Docker 網橋是宿主機虛擬出來的,並不是真實存在的網路裝置,外部網路是無法定址到的,這也意味著外部網路無法通過直接 Container-IP 訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過對映容器埠到宿主主機(埠對映),即 docker run 建立容器時候通過 -p 或 -P 引數來啟用,訪問容器的時候就通過[宿主機 IP]:[容器埠]訪問容器。

Docker 網路模型 配置 說明
host模式 --network=host 容器和宿主機共享 Network namespace。
containe模式 --network=container:ID 容器和另外一個容器共享 Network namespace。 kubernetes 中的 pod 就是多個容器共享一個 Network namespace。
none模式 --network=none 容器有獨立的 Network namespace,但並沒有對其進行任何網路設定,如分配 veth pair 和網橋連線,配置 IP 等。
bridge模式 --network=bridge 當 Docker 程序啟動時,會在主機上建立一個名為 docker0 的虛擬網橋,此主機上啟動的 Docker 容器會連線到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。(預設為該模式)
Host模式

​ 如果啟動容器的時候使用 host 模式,那麼這個容器將不會獲得一個獨立的 Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出自己的網絡卡,配置自己的IP等,而是使用宿主機的IP和埠。但是,容器其他方面,如檔案系統、程序列表等還是和宿主機隔離的。

​ 使用 host 模式的容器可以直接使用宿主機的 IP 地址與外界通訊,容器內部的服務埠也可以使用宿主機的 埠,不需要進行 NAT,host 最大的優勢就是網路效能比較好,但是 docker host 上已經使用的埠就不能再 用了,網路的隔離性不好。

​ 實現原理:docker容器名稱空間網路連線根名稱空間的網路。所以通過Host模式生成的多個容器的網路名稱空間是不同的。

​ 127.0.0.1 通過根名稱空間內的lo互通。

[root@arther-linux /]# docker run -d --name my_web --network host nginx
3196582b47ef7c75739e129ae0b77e75621e83a760b6f949bad716fcc7e7581e
[root@arther-linux /]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
3196582b47ef        nginx               "/docker-entrypoin..."   14 seconds ago      Up 13 seconds                                my_web

[root@arther-linux /]# curl 10.211.55.3:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
	...
# 連上了
Containe模式

​ 這個模式指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。 新建立的容器不會建立自己的網絡卡,配置自己的 IP,而是和一個指定的容器共享 IP、埠範圍等。同樣,兩個 容器除了網路方面,其他的如檔案系統、程序列表等還是隔離的。兩個容器的程序可以通過 lo 網絡卡裝置通訊。

​ 產生的網路名稱空間也盡不相同,意味著容器的網路資源彼此隔離。

# 建立test01容器
[root@arther-linux /]# docker run -itd --name test01 busybox
Unable to find image 'busybox:latest' locally
Trying to pull repository docker.io/library/busybox ... 
latest: Pulling from docker.io/library/busybox
5f5dd3e95e9f: Pull complete 
Digest: sha256:9f1c79411e054199210b4d489ae600a061595967adb643cd923f8515ad8123d2
Status: Downloaded newer image for docker.io/busybox:latest
40f28e664891327b410b96d0321afd4039aee8190b80f6112728421662f87c4c

# 通過--network將容器2的網路模式設定為contain模式,即網絡卡配置完全與test01一樣
[root@arther-linux /]# docker run -itd --name test02 --network "container:test01" busybox
c351447f5134383178788c16f1dbc231d72e73932c5cc42eb22bb241bbcf3667

# 比對兩者的網絡卡配置
[root@arther-linux /]# docker exec -it test02 sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:06  
          inet addr:172.17.0.6  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:656 (656.0 B)  TX bytes:656 (656.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

[root@arther-linux /]# docker exec -it test01 sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:06  
          inet addr:172.17.0.6  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:656 (656.0 B)  TX bytes:656 (656.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
              
# 簡單理解相當於test01給test02開了一個熱點,test02完全以test01的網絡卡配置連上網。
# 而test01則用了預設的虛擬docker容器網橋的方式。(bridge網路模式)
none 模式

使用 none 模式,Docker 容器擁有自己的 Network Namespace,但是,並不為 Docker 容器進行任何網路 配置。也就是說,這個 Docker 容器沒有網絡卡、IP、路由等資訊。需要我們自己為 Docker 容器新增網絡卡、配置IP 等。

這種網路模式下容器只有 lo 迴環網路,沒有其他網絡卡。none 模式可以在容器建立時通過--network=none 來指定。這種型別的網路沒有辦法聯網,封閉的網路能很好的保證容器的安全性。

[root@arther-linux /]# docker run -itd --name test03 --network none busybox
8289abbbcce7f92d58c2cf7335aa1843d2b337820a9e93150b041de173b42f06
[root@arther-linux /]# docker exec -it test03 sh
/ # ifconfig 
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
# 只有本地的Ip地址的配置資訊
bridge模式

​ 當Docker程序啟動時,會在主機上建立一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連線到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。

​ 從docker0子網中分配一個IP給容器使用,並設定docker0的IP地址為容器的預設閘道器。在主機上建立一對虛擬網絡卡 veth pair 裝置,Docker 將 veth pair 裝置的一段放在新建立的容器中,並命名為eth0 (容器的網絡卡),另一端放在主機中,以 vethxxx 這樣類似的名字命名,並將這個網路裝置加入到 docker0 網橋中。可以通過 brctl show 命令檢視。

​ 生成的容器的網路名稱空間不是同一個,是自己單獨的網路空間,彼此的網路資源的是隔離的。

[root@arther-linux /]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242310e39ed	no		veth3ce4ad4
							veth644e1ad
							vethb409f72
							vetheb71c43
							vethf614949

​ bridge 模式是 docker 的預設網路模式,不寫--net 引數,就是 bridge 模式。使用 docker run -p 時,docker實際是在 iptables 做了 DNAT 規則,實現埠轉發功能。可以使用 iptables -t nat -vnL 檢視。

​ 但是隻能實現宿主機中容器之間的聯絡,如果需要放上公網,可以在瀏覽器上訪問到,需要-p或-P對映預設埠。

[root@arther-linux /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:1c:42:ea:4f:e1 brd ff:ff:ff:ff:ff:ff
    inet 10.211.55.3/24 brd 10.211.55.255 scope global noprefixroute dynamic eth0
       valid_lft 1109sec preferred_lft 1109sec
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:84:eb:38 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:84:eb:38 brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:31:0e:39:ed 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:31ff:fe0e:39ed/64 scope link 
       valid_lft forever preferred_lft forever
67: veth644e1ad@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 7a:bc:96:53:eb:9d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::78bc:96ff:fe53:eb9d/64 scope link 
       valid_lft forever preferred_lft forever
69: vethb409f72@if68: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether c6:54:a5:51:f4:08 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::c454:a5ff:fe51:f408/64 scope link 
       valid_lft forever preferred_lft forever
71: veth3ce4ad4@if70: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 82:a4:55:a8:8f:9c brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::80a4:55ff:fea8:8f9c/64 scope link 
       valid_lft forever preferred_lft forever
73: vetheb71c43@if72: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether ba:00:f8:28:09:81 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::b800:f8ff:fe28:981/64 scope link 
       valid_lft forever preferred_lft forever
75: vethf614949@if74: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether be:d6:4d:59:70:ac brd ff:ff:ff:ff:ff:ff link-netnsid 4
    inet6 fe80::bcd6:4dff:fe59:70ac/64 scope link 
       valid_lft forever preferred_lft forever
77: veth1079c8b@if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 46:56:7e:68:87:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 5
    inet6 fe80::4456:7eff:fe68:87b3/64 scope link 
       valid_lft forever preferred_lft forever
      
# 在容器內
[root@arther-linux /]# docker exec -it test04 sh
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
# 自環


  • 檢視網橋

    [root@arther-linux ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    9fbb16915c1c        bridge              bridge              local
    4642eeb296dd        host                host                local
    ad403a4e2146        none                null                local
    
  • 建立網橋

    [root@arther-linux ~]# docker network create oldboy
    89568ea31576582e9454d613df96ca59813238330ca3cd71d3889a0a92d549bb
    
  • 清理網橋

    [root@arther-linux ~]# docker network prune 
    WARNING! This will remove all networks not used by at least one container.
    Are you sure you want to continue? [y/N] y
    Deleted Networks:
    oldboy
    
    # 不會清理預設網橋,只會清理自己自定義然後沒有工作的(即沒有生成轉發容器)的網橋
    
  • 刪除網橋

    [root@arther-linux ~]# docker network rm oldboy
    oldboy
    

五 Dockerfile 構建映象

​ Dockerfile 由一行行命令語句組成,並且支援以 # 開頭的註釋行,一般而言,Dockerfile 主體內容分為四部分:基礎映象資訊、維護者資訊、映象操作指令和容器啟動時執行指令。

​ Dockerfile 以從上到下的順序執行Dockerfile 的指令。為了指定基本映象,第一條指令必須是FROM。一個生命以 # 字元開頭則被視為註釋。可以在Docker檔案中使用RUN,CMD,FROM,EXPOSE,ENV 等指令。

1 FROM:指定基礎映象,必須為第一個命令

格式:
		FROM <image> 
  	FROM <image>:<tag> 
    FROM <image>@<digest> 
示例: FROM mysql:5.6 
注: 	tag 或 digest 是可選的,如果不使用這兩個值時,會使用 latest 版本的基礎映象

2 MAINTAINER:維護者資訊

格式:
		MAINTAINER <name> 
示例:
		MAINTAINER Jasper Xu 
  	MAINTAINER [email protected] 
    MAINTAINER Jasper Xu <[email protected]>

3 RUN:構建映象時執行的命令

RUN 用於在映象容器中執行命令,其有以下兩種命令執行方式: 
shell 執行 
格式:
		RUN <command> 
exec 執行 
格式:
		RUN ["executable", "param1", "param2"] 
  
示例:
		RUN ["executable", "param1", "param2"] 
  	RUN apk update RUN ["/etc/execfile", "arg1", "arg1"] 
    注: RUN 指令建立的中間映象會被快取,並會在下次構建中使用。如果不想使用這些快取映象,可以在構建 時指定--no-cache 引數,如:docker build --no-cache

4 ADD:將本地檔案新增到容器中

tar 型別檔案會自動解壓(網路壓縮資源不會被解壓)

格式:
  ADD <src>... <dest> 
  ADD ["<src>",... "<dest>"] 用於支援包含空格的路徑 
  
示例:
  ADD hom* /mydir/ 				# 新增所有以"hom"開頭的檔案 
  ADD hom?.txt /mydir/ 		# ? 替代一個單字元,例如:"home.txt" 
  ADD test relativeDir/ 	# 新增 "test" 到 `WORKDIR`/relativeDir/ 
  ADD test /absoluteDir/  # 新增 "test" 到 /absoluteDir/

5 COPY:功能類似 ADD,但是是不會自動解壓檔案,也不能訪問網路資源

指令:COPY 
功能描述:複製檔案到映象中 
語法:COPY < src>… < dest>|[“< src>”,… “< dest>”] 
提示:指令邏輯和 ADD 十分相似,同樣 Docker Daemon 會從編譯目錄尋找檔案或目錄,dest 為映象中的絕 對路徑或者相對於 WORKDIR 的路徑

6 CMD:構建容器後呼叫,也就是在容器啟動時才進行呼叫

格式:
	CMD ["executable","param1","param2"] (執行可執行檔案,優先) 
  CMD ["param1","param2"] (設定了 ENTRYPOINT,則直接呼叫 ENTRYPOINT 新增引數) 
  CMD command param1 param2 (執行 shell 內部命令) 
  
示例:
	CMD echo "This is a test." | wc - 
  CMD ["/usr/bin/wc","--help"]注: CMD 不同於 RUN,CMD 用於指定在容器啟動時所要執行的 命令,而 RUN 用																	 於指定映象構建時所要執行的命令。

7 LABEL:用於為映象新增元資料

格式:
		LABEL <key>=<value> <key>=<value> <key>=<value> ... 
  
示例:
		LABEL version="1.0" description="這是一個 Web 伺服器" by="IT 筆錄" 
  
注:
		使用 LABEL 指定元資料時,一條 LABEL 指定可以指定一或多條元資料,指定多條元資料時不同元資料之間 通過空格分隔。推薦將所有的元資料通過一條 LABEL 指令指定,以免生成過多的中間映象。

8 ENV:設定環境變數

格式:
		ENV <key> <value> #<key>之後的所有內容均會被視為其<value>的組成部分,因此,一次只能設定 一個變數ENV <key>=<value> ... #可以設定多個變數,每個變數為一個
  	"<key>=<value>"的鍵值對,如果 <key>中包含空格,可以使用\來進行轉義,也可以通過""來進行標示;另外,反斜線也可以用於續行 示例:
    ENV myName John Doe 
    ENV myDog Rex The Dog 
    ENV myCat=fluffy

9 EXPOSE:指定於外界互動的埠

格式:
		EXPOSE <port> [<port>...] 
示例:
		EXPOSE 80 443 
  	EXPOSE 8080 
    EXPOSE 11211/tcp 11211/udp 
    
注: 
		EXPOSE 並不會讓容器的埠訪問到主機。要使其可訪問,需要在 docker run 執行容器時通過-p 來 釋出這些埠,或通過-P 引數來發布 EXPOSE 匯出的所有埠

10 VOLUME:用於指定持久化目錄

格式:
		VOLUME ["/path/to/dir"] 
  
示例:
		VOLUME ["/data"] 
  	VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"] 
    
注: 一個卷可以存在於一個或多個容器的指定目錄,該目錄可以繞過聯合檔案系統,並具有以下功能: 
1 卷可以容器間共享和重用 
2 容器並不一定要和其它容器共享卷 
3 修改卷後會立即生效 
4 對卷的修改不會對映象產生影響 
5 卷會一直存在,直到沒有任何容器在使用它

11 WORKDIR:工作目錄,類似於 cd 命令

格式:
		WORKDIR /path/to/workdir 
  
示例:
		WORKDIR /a (這時工作目錄為/a) 
  	WORKDIR b (這時工作目錄為/a/b) 
    WORKDIR c (這時工作目錄為/a/b/c) 
    
注: 
		通過 WORKDIR 設定工作目錄後,Dockerfile 中其後的命令 RUN、CMD、ENTRYPOINT、ADD、COPY 等命令都會在該目錄下執行。在使用 docker run 執行容器時,可以通過-w 引數覆蓋構建時所設定的工作目錄。

12 ARG:用於指定傳遞給構建執行時的變數

格式:
		ARG <name>[=<default value>] 
  
示例:
		ARG site ARG build_user=www

13 ONBUILD:用於設定映象觸發器

格式: ONBUILD [INSTRUCTION] 
示例:
			ONBUILD ADD . /app/src 
  		ONBUILD RUN /usr/local/bin/python-build --dir /app/src 
    
注: 
			當所構建的映象被用做其它映象的基礎映象,該映象中的觸發器將會被鑰觸發

14 Dockerfile 構建映象案例

製作映象

# 寫Dockerfile
[root@arther-linux test]# cat Dockerfile 

# 指定基礎映象
FROM python:3.6.12

# 安裝django
RUN pip3 install django==2.2.2 -i https://pypi.douban.com/simple/

# 建立app專案
RUN django-admin startproject app

# 建立application
RUN cd /app && django-admin startapp docker

# 啟動
CMD cd /app && python3 manage.py runserver 0.0.0.0:8000



[root@arther-linux /]# docker build -t test/busybox:v1 .
Error checking context: 'no permission to read from '/media/psf/Home/Library/Preferences/com.apple.AddressBook.plist''.
# 不能寫絕對路徑,要相對路徑


# 會自動執行Dockerfile中的程式碼
[root@arther-linux test]# docker build -t test:v1 .
Sending build context to Docker daemon 718.4 MB
Step 1/5 : FROM python:3.6.12
 ---> 178f37a5a906
Step 2/5 : RUN pip3 install django==2.2.2 -i https://pypi.douban.com/simple/
 ---> Running in 15cb7581d493

Looking in indexes: https://pypi.douban.com/simple/
Collecting django==2.2.2
  Downloading https://pypi.doubanio.com/packages/eb/4b/743d5008fc7432c714d753e1fc7ee56c6a776dc566cc6cfb4136d46cdcbb/Django-2.2.2-py3-none-any.whl (7.4 MB)
Collecting pytz
  Downloading https://pypi.doubanio.com/packages/12/f8/ff09af6ff61a3efaad5f61ba5facdf17e7722c4393f7d8a66674d2dbd29f/pytz-2020.4-py2.py3-none-any.whl (509 kB)
Collecting sqlparse
  Downloading https://pypi.doubanio.com/packages/14/05/6e8eb62ca685b10e34051a80d7ea94b7137369d8c0be5c3b9d9b6e3f5dae/sqlparse-0.4.1-py3-none-any.whl (42 kB)
Installing collected packages: sqlparse, pytz, django
Successfully installed django-2.2.2 pytz-2020.4 sqlparse-0.4.1
 ---> 01fa3f47e5e8
Removing intermediate container 15cb7581d493
Step 3/5 : RUN django-admin startproject app
 ---> Running in 0e999307c880

 ---> 43939255f0b9
Removing intermediate container 0e999307c880
Step 4/5 : RUN cd /app && django-admin startapp docker
 ---> Running in fe0ae86cb44a

 ---> cbf131ce037d
Removing intermediate container fe0ae86cb44a
Step 5/5 : CMD cd /app && python3 manage.py runserver 0.0.0.0:8000
 ---> Running in 22c3f43f2dfa
 ---> 02429b584fa7
Removing intermediate container 22c3f43f2dfa
Successfully built 02429b584fa7


# 生成容器
[root@arther-linux test]# docker run -d -it test:v1
693423b16b04871a70b20df865aa730729154ec07a15e125fe1f9cfe6433774b

[root@arther-linux test]# docker exec -it  pensive_jang bash

root@693423b16b04:/usr/local/bin# ls
2to3	     django-admin     easy_install-3.6	idle3.6  pip3.6  pydoc3.6	python3		python3.6-config   pyvenv      wheel
2to3-3.6     django-admin.py  idle		pip	 pydoc	 python		python3-config	python3.6m	   pyvenv-3.6
__pycache__  easy_install     idle3		pip3	 pydoc3  python-config	python3.6	python3.6m-config  sqlformat

製作映象,在容器中設定nginx反向代理

http://nginx.org/en/linux_packages.html#RHEL-CentOS

# 在此網站獲取下載nginx的步驟

# 在此檔案路徑下寫入官網提供的nginx配置
[root@arther-linux ~]# touch /etc/yum.repos.d/nginx.repo
[root@arther-linux ~]# vim /etc/yum.repos.d/nginx.repo

# 生成yum快取
[root@arther-linux ~]# yum makecache 

# 正式安裝naginx
[root@arther-linux ~]# yum install nginx -y


# 以之前定義的映象為基本生成容器,對映
[root@arther-linux ~]# docker run -d -p 8080:8000 test:v1

======配置代理=======
'''
反向代理,以伺服器為主,伺服器打集群后下有多臺主機,使用者不需知道哪一臺的主機IP,只需知道主伺服器IP即可訪問

'''
# 先清空預設配置
[root@arther-linux conf.d]# >default.conf 


upstream django {
    server 127.0.0.1:8080;   # 代理伺服器的IP與埠,本機測試的IP地址
}

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://django;
        index index.html index.htm;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }}

# 測試配置是否成功
[root@arther-linux conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  
# 再啟動nginx
[root@arther-linux ~]# nginx -g 'daemon off;'  

# 製作映象檔案Dockerfile
[root@arther-linux ~]# mkdir teach
[root@arther-linux ~]# cd teach
[root@arther-linux teach]# mkdir django
[root@arther-linux teach]# mkdir nginx
[root@arther-linux teach]# cd nginx
[root@arther-linux nginx]# touch Dockerfile
[root@arther-linux nginx]# vim Dockerfile 
============寫入檔案=============
# 設定基礎映象
FROM centos:7

# 安裝yum工具
# 設定基礎映象
FROM centos:7

RUN yum install wget -y

# 換源
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

RUN cd /etc/yum.repos.d && wget http://mirrors.163.com/.help/CentOS7-Base-163.repo

RUN mv /etc/yum.repos.d/CentOS7-Base-163.repo /etc/yum.repos.d/CentOS-Base.repo

# 建立nginx源的檔案
ADD nginx.repo /etc/yum.repos.d/

# 重新整理yum快取
RUN yum makecache

# 安裝yum工具
RUN yum install yum-utils -y

# 安裝Nginx
RUN yum install nginx -y

# 複製配置檔案
ADD default.conf /etc/nginx/conf.d/

# 設定啟動命令
CMD nginx -g 'daemon off;'                                                                    

===============================
# 換源或是配置不能直接寫入,只能用mv指令移入
[root@arther-linux nginx]# vim nginx.repo
# 把源的配置寫入,方便之後製作映象時寫入的操作

[root@arther-linux nginx]# vim default.conf
upstream django {
    server django:8000;       # 此時在容器裡執行,到時候被代理容器命名為django,8000埠對應,django	
}															# Dockerfile 中的 0.0.0.0:8000

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://django;
        index index.html index.htm;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }}


[root@arther-linux ~]# docker network create oldboy

# 執行製作映象命令
[root@arther-linux ~]# docker build -t nginx:v1 . -f ~/teach/nginx/Dockerfile
# -f指定了尋找Dockerfile在當前資料夾
[root@arther-linux ~]# docker build -t django -f Dockerfile .

# 用同一個網橋啟動容器
docker run -dit --name nginx --network oldboy nginx:v1
# 製作容器時,需要命名為之前default.conf 設定的代理的容器名
docker run -dit --name nginx --network oldboy django:latest # Dockerfile在上一部分已寫好

# 檢視是否執行
[root@arther-linux ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
07c6c8459f15        nginx:v1            "/bin/sh -c 'nginx -…"   3 hours ago         Up 3 hours                              nginx
04f96e388361        django:latest       "/bin/sh -c 'cd /app…"   3 hours ago         Up 3 hours                              django  
  
  
# 測試連線
[root@arther-linux ~]# docker exec -it nginx bash
[root@07c6c8459f15 /]# ping django
PING django (172.18.0.2) 56(84) bytes of data.
64 bytes from django.oldboy (172.18.0.2): icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from django.oldboy (172.18.0.2): icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from django.oldboy (172.18.0.2): icmp_seq=3 ttl=64 time=0.066 ms