Docker快速指南


Docker使用Go語言開發,基於Linux內核的cgroup、namespace以及AUFS等技術對進程進行封裝隔離,是一種操作系統層面的虛擬化技術。由於隔離的進程獨立於宿主和其它的隔離的進程,因此也稱其為容器。

Docker則使用宿主機內核提供的隔離機制創建沙盒環境,容器內的應用進程直接運行於宿主的內核。 因為容器內沒有虛擬硬件和內核,容器在啟動時間、執行效率、內存占用以及鏡像大小等方面相對於傳統虛擬機都擁有很大優勢。

Docker容器將程序及其運行環境打包在一起,鏡像創建后可以在任何安裝了Docker的系統上運行,無需配置運行環境, 加之較小的鏡像體積極大方便了協作開發和部署。

使用Dockerfile將鏡像構建過程透明化,也便於開發和運維人員理解程序的運行環境。

Docker相對於虛擬機的優勢來源於它運行與宿主內核而減少了開銷,這使得Docker不能虛擬不同的內核環境。也就是說我們可以很容易地在Windows操作系統上啟動一個Linux虛擬機,但是在Windows上啟動一個基於Linux的Docker容器則是很困難的事情。

docker官方已經發布了docker for macdocker for windows。目前docker for mac使用MAC OS內核提供的HyperKit虛擬化技術代替了docker-toolbox采用的使用Linux虛擬機提供支持的方式。

目錄:

What's Docker

cgroup和namespace是Linux內核提供的兩種隔離機制,是Docker虛擬化的技術基礎:

  • cgroup: 全名Control Groups, Linux內核提供的用於監控和管理進程組占用資源的機制。 這里的資源包括CPU,內存和IO等硬件資源。
  • namespace: 為某個進程提供獨立的空間,包括獨立的:
    • 進程樹: 進程擁有獨立的init進程及其下進程樹
    • 文件系統: 進程擁有獨立的根目錄/及其下目錄樹
    • 用戶: 進程可以定義自己的用戶,組和權限系統
    • 協議棧: 進程可以擁有獨立的ip地址及tcp/udp端口空間
    • 其它

在了解隔離機制之后我們可以了解Docker中的兩個核心概念:

  • 容器:容器的本質是進程,它擁有獨立的命名空間。因此容器表現很像一個虛擬操作系統,擁有自己的進程樹,文件系統等。
  • 鏡像:鏡像是容器運行依賴的文件系統,就像每個Linux操作系統時都需要掛載root文件系統/,鏡像就是容器的root文件系統。

Docker采用服務端/客戶端架構:

  • 守護進程(dockerd): Docker服務端每個dockerd下可以運行多個容器,此外還提供了鏡像和容器管理的功能。
  • 客戶端: 通過API與dockerd通信進行操作,官方提供了命令行客戶端以及Go和Python語言的SDK
  • 宿主機:用於運行dockerd及其容器的操作系統環境
  • Registry:Docker鏡像存儲中心,用於管理和共享docker鏡像。官方存儲中心DockerHub中提供了大量官方和第三方鏡像。

Docker采用UnionFS技術將鏡像設計為分層結構,即一個鏡像分為多層,每一層在上一層的基礎上構建(即存儲增量)。在容器中只能看到所有層疊加后的結果,隱藏了分層的結構。因為鏡像層會被其它層依賴,為了保證下層能正常工作, 鏡像層在創建后就無法進行修改。

Get Started

Docker目前分為免費的社區版(CE)和付費的商業版(EE)兩種, 這里我們選用社區版。 Docker官網上提供了各種常用操作系統的安裝說明:

下面看一個簡單的示例:

finley@mbp:$ uname
Darwin
finley@mbp:$ docker run -it ubuntu
root@528ab91753d6:/# uname
Linux

在執行docker run命令后發現我們已經從宿主機Mac的終端進入到了Linux終端中。 這個運行中的"Linux"就是容器,啟動這個虛擬的Linux環境所需的文件即是鏡像。

上面的示例中我們使用docker代替了ubuntu虛擬機,對比之下docker在鏡像大小,啟動時間和運行內存占用方面都具有巨大的優勢。 

因為啟動docker容器的開銷和啟動相應進程的開銷基本相同, 因此完全可以使用docker代替原生進程, 避免復雜的編譯安裝配置過程。

$ docker run -p 6379:6379 -d redis
3a5748eef653
$ redis-cli
127.0.0.1:6379> keys *
(empty list or set)

這個示例中我們一鍵安裝並啟動了redis-server。

在終端中輸入docker命令則會顯示所有命令和使用幫助, 在docker命令后添加--help選項可以查看該命令的幫助信息, 如docker run --help可以查看run命令的幫助。

鏡像

本節將簡單介紹如何搜索和管理鏡像, 為介紹容器做准備。更多關於鏡像的構建和共享的內容將在下文中介紹。

docker images

docker images命令用於顯示本地所有鏡像:

REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 00fd29ccc6f1 3 weeks ago 111MB
redis latest 1e70071f4af4 4 weeks ago 107MB

和其它軟件一樣docker鏡像也可以演進出不同版本,tag用於標識鏡像的版本。

repository代表同一鏡像多個版本的集合, 它的值是一個URI用於全局唯一標識一組鏡像,如"registry.cn-hangzhou.aliyuncs.com/acs/agent"。

對於DockerHub中的鏡像則會省略倉庫的地址,諸如dorowu/ubuntu-desktop-lxde-vncubuntu就是DockerHub中的鏡像。

由此可見,repositorytag可以唯一標識docker鏡像。

除此之外每個鏡像還擁有一個摘要(DIGEST),docker images --digest可以顯示鏡像的摘要。

DockerHub是docker官方提供的公有倉庫,docker search命令用於根據關鍵字搜索DockerHub中的鏡像:

format: docker search TERM
demo: docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a ... 7076 [OK]
dorowu/ubuntu-desktop-lxde-vnc Ubuntu with openssh-server and NoVNC 156 [OK]

docker pull

docker pull命令用於從遠程下載鏡像,可以通過NAME:TAGNAME@DIGEST的格式來指明目標鏡像。

當只提供了鏡像NAME時,默認下載tag為latest的鏡像。

$docker pull ubuntu
$docker pull ubuntu:16.04
$docker pull ubuntu@sha256:fbaf303d18563e57a3c1a0005356ad102509b60884f3aa89ef9a90c0ea5d1212

NAME也可以是私有倉庫中一個REPOSITORY的URI。

docker rmi

docker rmi用於刪除鏡像,可以使用IMAGE IDREPOSITORY:TAG來標記一個容器。

容器

docker run

docker run命令用於新建一個容器並啟動, 是最重要的和最常用的docker命令之一。

format: docker run IMAGE CMD ARGS

docker run命令的標准執行流程包括:

  • 檢查本地是否包含指定的鏡像,若不存在就從公有倉庫下載
  • 在只讀的基礎鏡像層上掛載一個可讀寫層,創建容器的文件系統
  • 根據文件系統啟動容器
  • 將容器與宿主機橋接
  • 用指定的身份登錄容器,並在指定目錄下執行CMD ARGS參數指定的命令
  • 在命令執行完成后關閉容器

docker容器在命令執行完畢后會自動退出, 容器的生存周期僅決定於執行命令所需的時間。 如果在容器中執行bash等長期運行的命令, 就可以保證容器長期運行。

docker run命令默認會把標准輸出流(stdout)重定向到終端,並與容器保持連接狀態(attach)。

在attach狀態下, 容器退出之前doceker run命令不會返回,而是在終端回顯容器的輸出。 若發出kill信號(如ctrl + c快捷鍵)殺死docekr run, 那么容器也會提前退出。

容器對文件系統的修改在可讀寫層,不會對鏡像產生影響, 除非使用docker commit創建新的鏡像層。 容器退出后其文件系統仍將保存在磁盤中,下次啟動后會保留所有修改。

打開終端

docker run命令默認將容器的標准輸出流重定向到終端, 但是沒有將終端的標准輸入流(stdin)重定向到容器。 也就是說,容器無法接收我們在終端中輸入的命令。

使用-i--interactive選項會保持容器的輸入流(stdin)打開,即使docker run不與容器保持attach狀態。

docker run -i ubuntu bash命令可以打開一個ubuntu終端, 該終端也可以接受我們輸入的指令。

和標准的Linux系統一樣,docker鏡像也為用戶指定了默認終端。 使用-t--tty選項會打開一個虛擬終端(Pseudo-TTY)。

也就是說,docker run -it ubuntu命令可以輕松地打開一個可交互ubuntu虛擬環境。

后台運行

docker run命令默認與容器保持連接狀態(attach), -d--detach選項可以與容器斷開連接。 docker run命令在顯示容器ID后立即返回,容器則會在后台運行。

上文redis-server的示例即使用了-d選項, docker run立即返回, redis-server在后台繼續運行。

$ docker run -p 6379:6379 -d redis
3a5748eef653
$ redis-cli
127.0.0.1:6379>

端口映射

如上文中redis-server示例, 我們經常使用docker容器提供服務,因此需要docker容器監聽宿主機的某個端口。

docker run -p 6379:6379 -d redis將對宿主機TCP6379端口的訪問映射到容器的TCP6379端口。

-p 6379:6379/udp則可以映射udp訪問(雖然對redis-server來說沒有意義)。 多個-p選項可以映射多個端口docker run -p 80:8080 -p 8080:8081 -d my_server.

端口映射是將對宿主機某個端口的訪問映射到容器的某個端口上, 容器訪問宿主機端口不需要配置端口映射。


掛載數據卷

-v選項可以將宿主機上某個目錄掛載到容器中的某個目錄

$ ls ~/myvol
history.txt
$ docker run -it -v ~/myvol:/app ubuntu
root@e690c508219e:/# ls /app
history.txt

上述指令將宿主機目錄~/myvol掛載到鏡像的/app目錄下,/app目錄下原來的內容會被隱藏而是顯示宿主機目錄~/myvol下的內容。

這種方式我們稱為在容器上掛載了數據卷,對數據卷的讀寫獨立於容器之外:

  • 容器對數據卷的修改將立即存儲到數據卷所在的(即宿主機的文件系統)上
  • 除非指明刪除數據卷,否則容器刪除不會對數據卷產生影響
  • 其它進程對數據卷的修改將立即生效

若數據卷~/myvol或掛載點/app不存在的時候, docker會自動創建空目錄。

docker提供了獨立於容器的數據卷管理功能,參考docker volume

為容器命名

每個容器都擁有一個唯一的CONTAINER ID來標識,但ID不便於記憶和使用。 因此在docker run創建容器時可以使用--name選項來為容器指定一個名稱。

在某個dockerd中容器名稱是唯一的, 我們可以使用容器名來唯一指定容器。

示例:docker run --name my_ubuntu -it ubuntu

退出時自動刪除

docker run --rm選項會在容器退出時自動刪除容器。 使用該命令時需謹慎, 容器一旦刪除便不可恢復。

自定義工作目錄

docker run -w PATH選項會在啟動容器時,使用PATH參數指定的路徑作為工作目錄。

docker create

docker create命令與docker run指令極為相似,區別在於docker run創建容器后自動啟動容器, 而docker create不自動啟動容器需要使用docker start命令來啟動。

docker ps

docker ps命令用於顯示容器的信息,默認情況下顯示運行中的容器:

finley@mbp $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3a5748eef653 redis "docker-entrypoint..." 3 hours ago Up 3 hours 0.0.0.0:6379->6379/tcp redis-server
c10921921bfb ubuntu "/bin/bash" 3 hours ago Up 52 seconds my_ubuntu

-a選項可以顯示包括已停止容器在內的所有容器信息。

docker start

docker start命令用於啟動一個已停止的容器,默認情況下不與容器連接(attach)也不將輸入重定向到容器。

$ docker run --name redis-server -p 6379:6379 redis
$ docker stop redis-server # 此時已經存在一個名為redis-server的已停止容器
$ docker start redis-server
redis-server
$ redis-cli
127.0.0.1:6379>

若使用-a--attach選項將docker start與容器連接(attach), 終端將回顯容器輸出。

-i--interactive選項則會將輸入重定向到容器。

$ docker run --name my_ubuntu -it ubuntu
root@c10921921bfb # exit
# 此時已經存在一個名為my_ubuntu的已停止容器
$ docker start -ai my_ubuntu
root@c10921921bfb:/#

docker exec

docker exec用於讓一個正在運行的容器執行命令,命令執行完成后docker exec將返回容器繼續運行。

$ docker run --name my_ubuntu -d ubuntu
$ docker exec my_ubuntu ls
home bin ...

默認情況下docker exec與容器連接,-d--detach選項可以不與容器連接而在后台執行命令。

docker run命令類似, -i選項用於將標准輸入重定向到容器以便接收用戶輸入, -t選項可以打開終端。

$docker exec -it my_ubuntu bash
root@c10921921bfb:/# 

docker attach

docker attach命令用於與容器連接, 即將容器輸出流重定向到終端,終端輸入流重定向到容器。

$ docker attach my_ubuntu
# 再按一次回車
root@c10921921bfb:/#

當容器沒有輸出時終端中沒有回顯,可能令用戶誤以為卡死。 attach之后再次輸入回車, bash將回顯命令行提示符。

attach狀態下ctrl + c快捷鍵會發送SIGKILL信號中止容器, 而ctrl + p, ctrl + q快捷鍵會退出attach容器繼續運行。

docker stop

docker stop用於終止容器的運行

$docker stop redis-server

docker stop命令會先發送SIGTERM信號要求容器中的進程執行退出操作,若達到超時時間(默認10s)容器仍未退出則會發送SIGKILL信號強制退出。

-t-time選項可以秒為單位設置強制殺死之前的等待時間:

$docker stop -t 20 redis-server

docker kill

docker kill命令將直接向容器發送SIGKILL命令停止容器:

$docker kill redis-server

-s--signal選項可以向容器發送指定的信號:

docker kill -s SIGINT my_ubuntu

docker cp

docker cp命令負責在運行的容器和宿主機之間復制文件:

# format: docker cp FROM TO 
$ docker cp test.txt my_ubuntu:/root/test.txt
$ docker cp my_ubuntu:/root/test.txt test.txt 

docker rm

docker rm用於刪除一個鏡像,通過鏡像ID或鏡像名來指定要刪除的鏡像, 默認情況下只能刪除已退出的鏡像:

$ docker stop my_ubuntu
$ docker rm my_ubuntu

-f--force選項可以強制刪除運行中的鏡像。

-v--volumes選項將刪除所有掛載的數據卷。

docker volume

docker volume系列指令用於獨立的管理數據卷, 請先閱讀docker run:掛載數據卷

create

將宿主機上一個目錄創建為數據卷:

# format: docker volume create PATH
$ docker volume create myvol

ls

查看所有數據卷:

docker volume ls
DRIVER  VOLUME NAME
local   0c28b79a9b3f
local   myvol

inspect

查看某個數據卷的詳細信息:

docker volume inspect myvol
[
    {
        "CreatedAt": "2018-01-16T09:04:16Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/myvol/_data",
        "Name": "myvol",
        "Options": {},
        "Scope": "local"
    }
]

rm

刪除某個數據卷:

docker volume remove myvol
myvol

prune

刪除所有未被使用的數據卷:

docker volume prune
WARNING! This will remove all volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B

使用數據卷

docker rundocker create命令可以使用-v--volume選項來使用數據卷:

docker run -d -it -v myvol:/app ubuntu

docker會優先尋找數據卷列表中的myvol而不是當前目錄下的myvol子目錄。

若找不到myvol數據卷且當前目錄下也不存在myvol子目錄,docker會自動創建myvol數據卷不會再當前目錄下創建子目錄。

--mount選項雖然語法復雜,但是可以配置更多選項:

docker run -it --mount source=my_volume,target=/app ubuntu

構建鏡像

上文中已經介紹了如何獲取和使用已有鏡像,接下來介紹如何構建自己的鏡像。

我們可以將自己的程序及其運行環境打包成Docker容器,部署到服務器或者共享給其它開發者免去配置環境的煩惱。

docker diff

前文已經提到過Docker鏡像采用分層結構,容器運行時無法修改鏡像的內容,而是在鏡像層上掛載了一個可讀寫層。

docker diff命令可以查看容器對鏡像的修改:

$ docker run --name my_ubuntu -it ubuntu 
# if exists: docker start -ai my_ubuntu
root@c10921921bfb:~# echo "Hello, from finley" > hello.txt
root@c10921921bfb:~# exit
➜  ~ docker diff my_ubuntu
C /root
A /root/.bash_history
A /root/hello.txt

我們打開一個ubuntu容器在/root目錄中創建了hello.txt文件, 並在其中寫入"Hello, from finley"。

通過docker diff可以看出這個操作產生了三個影響:

  • 工作目錄修改為/root, C代表變更工作目錄
  • 命令歷史.bash_history文件改變, A代表文件或目錄內容發生改變
  • 修改了文件hello.txt

docker commit

docker commit命令根據容器對鏡像的修改創建新的鏡像層

# format: docker commit CONTAINER REPOSITORY[:TAG]
$docker commit my_ubuntu my_ubuntu:2018_01_14
sha256:8096f47d8d6b80e52e617030938c7a83a9d50bafd73915d6952675e7126bb38a
$docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my_ubuntu 2018_01_14 8096f47d8d6b Less than a second ago 111MB

-a--author選項可以指定容器的作者, -m--message可以添加備注信息:

$docker commit \
    -a "finley<finley@finley.pw>"  \
    -m "say hello" \
    my_ubuntu my_ubuntu:2018_01_14

-c--change選項可以添加一系列Dockerfile指令,關於Dockerfile的內容我們將在下文介紹。

docker tag

docker tag命令用於為鏡像創建一個別名。

# format: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
$ docker tag ubuntu my_ubuntu

TARGET_IMAGE可以是私有倉庫REPOSITORY的URI,tag命令經常被用來協助將鏡像推送到私有倉庫。

docker history

docker history命令用於顯示鏡像各層的信息,即查看commit歷史:

$ docker history ubuntu

Dockerfile

docker commit命令雖然可以很方便的創建新的鏡像,但是我們在容器內操作(特別是嘗試性的操作)可能會在新鏡像內產生無關的內容,如命令歷史和日志等。

Dockerfile是控制鏡像構建過程的腳本,使用Dockerfile可以有效避免鏡像中包含無關內容。

Dockerfile中包含多行指令,每個指令會在鏡像中創建一層。

FROM nginx
RUN echo '<h1>Hello from finley!</h1>' > /usr/share/nginx/html/index.html
$ docker build -t nginx_hello .
Step 1/2 : FROM nginx
  ---> 3f8a4339aadd
Step 2/2 : RUN echo '<h1>Hello from finley!</h1>' > /usr/share/nginx/html/index.html
  ---> Running in 2b3c5df09f9c
  ---> a918263d0f2f
Removing intermediate container 2b3c5df09f9c
Successfully built a918263d0f2f
Successfully tagged nginx_hello:latest
$ docker run --name nginx_hello -p 80:80 -d --rm nginx_hello
$ curl localhost
<h1>Hello from finley!</h1>

上面示例中我們以nginx為基礎構建了一個新鏡像,並啟動它提供服務。

在具體介紹Dockerfile的指令之前,我們先介紹一下docker build命令。

docker build指令用於根據Dockerfile構建鏡像,通常該指令需要一個PATH參數來指定某個目錄做為構建上下文(context)。

-f--file選項用於在構建上下文指定Dockerfile文件的路徑, 默認為PATH/Dockerfile

-t--tag選項用於為鏡像指定標簽,默認情況下名稱仍然與基礎鏡像相同, 而-t NAME:TAG則會指定容器的名稱。

除了使用一個目錄作為構建上下文之外,也可以使用tar壓縮包、git倉庫作為上下文, 甚至從標准輸入中讀取Dockerfile或tar進行構建。

接下來介紹常用的Dockerfile命令:

FROM

FROM指令用於指定構建容器的基礎鏡像,標記鏡像的語法與docker pull命令相同。

除了使用已存在的鏡像作為基礎鏡像之外還有一個特殊的鏡像scratch, 它是一個空鏡像。

我們可以把靜態編譯的可執行文件放入空白鏡像中,由內核直接執行可以極大的降低鏡像的體積。

RUN

RUN命令在鏡像中創建一個容器並執行指定指令,執行結束后commit修改作為鏡像的一層。

上文示例中的Step2展示了RUN指令運行的過程:

  • 創建一個中間容器(intermediate container): 2b3c5df09f9c
  • 運行命令echo '<h1>Hello from finley!</h1>' > /usr/share/nginx/html/index.html
  • 將修改提交,產生新的容器: a918263d0f2f
  • 刪除中間容器:2b3c5df09f9c

RUN命令有兩種參數格式:

  • 命令行式: RUN ls -al
  • 函數調用式: RUN ["ls", "-al"]

在實際執行過程中命令行式指令會被映射為RUN ["sh", "-c", "ls", "-al"]

因為每個RUN指令都會生成一層鏡像, 因此最好用&&將多條指令連接而不是寫多條RUN指令。

COPY

COPY from to指令將文件或目錄從構建上下文(context)將文件復制到鏡像內部。

COPY ./config.json /root/config.json

WORKDIR

WORKDIR path命令用於指定容器的默認工作目錄。

WORKDIR命令對Dockerfile中的后續命令都有影響, 除非有另一條WORKDIR命令修改了工作目錄

上文已經介紹過每條RUN指令都會創建一個臨時容器, 因此RUN cd PATH &&...只對同一條RUN中的后續指令有效。

USER

USER命令用於指定容器中的當前用戶:

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN redis-server

WORKDIR命令一樣,USER指令直到下一條USER指令之前始終有效。

CMD

CMD命令用於指定啟動容器的指令, 和RUN命令一樣有兩種格式。

EXPOSE

EXPOSE命令用於聲明需要暴露哪些接口,注意EXPOSE命令沒有建立端口映射, 需要在創建容器時啟動端口映射。

ENV

ENV命令用於為容器設置環境變量:

ENV DEBUG=on VERSION='1.0' 

ENTRYPOINT

ENTRYPOINT指令和CMD一樣,用於指定啟動容器的指令。 當指定了ENTRYPOINT之后,CMD命令的內容將被作為參數傳遞給ENTRYPOINT指定的指令。

首先創建一個容器:

FROM ubuntu
CMD ls
$ docker build -t ls:v1 .
$ docker run --rm ls:v1
bin boot dev etc home lib ...

如果我們試圖傳遞-al選項給ls以顯示更詳細的信息:

$ docker docker run --rm ls -al
container_linux.go:265: starting container process caused "exec: \"-al\": executable file not found in $PATH"

根據docker run的語法我們試圖讓ls鏡像執行-al命令代替默認命令, 這當然行不通。

用ENTRYPOINT代替CMD:

FROM ubuntu
ENTRYPOINT ["ls"]

重新創建:

$ docker build -t ls:v2 .
$ docker run --rm ls:v2 -al
total 72
drwxr-xr-x   1 root root 4096 Jan 14 13:29 .
drwxr-xr-x   1 root root 4096 Jan 14 13:29 ..
-rwxr-xr-x   1 root root    0 Jan 14 13:29 .dockerenv
drwxr-xr-x   2 root root 4096 Dec  1 21:53 bin
drwxr-xr-x   2 root root 4096 Apr 12  2016 boot
drwxr-xr-x   5 root root  340 Jan 14 13:29 dev

ENTRYPOINT通常用於在執行容器CMD做一些准備工作, 比如官方redis鏡像中:

FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]

docker run --entrypoint CMD可以用來更改容器的ENTRYPOINT。

共享鏡像

現在我們已經了解如何構造自己的鏡像,接下來的問題是如何將鏡像分享給其它開發者或者部署到服務器。

docker export

docker export命令用於導出容器的快照, 默認輸出到標准輸出流,需要將輸出重定向到文件進行保存。

# format: docker export CONTAINER > TAR
$ docker export my_ubuntu > my_ubuntu.tar

或者使用-o--output選項

$ docker export -o my_ubuntu.tar my_ubuntu

docker export命令導出時會新建一個空白鏡像然后將容器文件系統的內容寫入,不包含容器基礎鏡像各層和tag等信息。

docker save

docker save用於將鏡像存儲為tar壓縮包,默認導出到標准輸出流需要重定向以寫入文件

# format: docker save IMAGE > TAR
$ docker save ubuntu > ubuntu.tar

或者使用-o--output選項

$ docker save -o ubuntu.tar ubuntu

docker save命令會將鏡像各層及其tag信息導出到文件。

docker import

docker import命令用於導入tar格式的快照,生成的鏡像只有一層不導入各層和tag信息。

$ docker import my_ubuntu.tar my_ubuntu:v2

該指令與docker export相對用於導入容器鏡像,但也可以導入docker save生成的tar文件。

docker load

docker load用於導入tar格式的鏡像副本,導入時保留各層和tag等元數據, 因此不需要指定鏡像名和tag。

默認從標准輸入流導入:

$ cat ubuntu.tar | docker load

或者使用-i--input選項:

docker load -i ubuntu.tar

docker load命令與docker save命令相對,因為缺少元數據不能導入docker export生成的tar文件。

Registry

雖然docker支持以文件的形式導入導出鏡像,但這種方式對於共享鏡像來說仍十分不便。

Docker官方提供了一個registry鏡像,我們可以使用它輕松搭建私有倉庫。

$ mkdir registry
$ docker run -d \
    -p 5000:5000 \
    -v registry:/var/lib/registry \
    registry

-v選項將./registry目錄掛載到了容器中,這個目錄將用來實際存儲鏡像。

docker默認采用HTTPS方式推送和拉取鏡像,本文不再介紹如何為私有倉庫配置HTTPS證書。

私有倉庫可以配置權限認證,僅授權用戶才能推送或拉取鏡像,這里也不再詳細介紹權限認證相關功能。

docker push

docker push命令用於將鏡像推送到倉庫,推送到的倉庫由鏡像的REPOSITORY屬性決定。

$ docker tag ubuntu 127.0.0.1:5000/finley/my_ubuntu:v1
$ docker docker push 127.0.0.1:5000/finley/my_ubuntu:v1
The push refers to a repository [127.0.0.1:5000/finley/my_ubuntu]
f17fc24fb8d0: Mounted from registry/my_ubuntu
6458f770d435: Mounted from registry/my_ubuntu
5a876f8f1a3d: Mounted from registry/my_ubuntu
d2f8c05d353b: Mounted from registry/my_ubuntu
48e0baf45d4d: Mounted from registry/my_ubuntu
v1: digest: sha256:f871d0805ee3ce1c52b0608108dbdf1b447a34d22d5c7278a3a9dd78fc12c663 size: 1357
$ curl 127.0.0.1:5000/v2/_catalog
{"repositories":["registry/my_ubuntu"]}

首先,使用docker tag命令給想要推送的鏡像unbuntu:latest創建一個別名127.0.0.1:5000/registry/my_ubuntu:v1

在這個URI中, 127.0.0.1:5000是Registry的地址,finley是私有倉庫中的一個命名空間, my_ubuntu是私有倉庫中的一個REPOSITORY。

訪問127.0.0.1:5000/v2/_catalog來查看私有倉庫中的鏡像。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM