Docker概述 第二章

yoqz3865 8年前發布 | 14K 次閱讀 Docker

在本次介紹Docker的迷你系列 第一章 中,我們了解了什么使Docker如此特別、虛擬機與容器之間的區別和組成Docker的主要組件。

在本博文中,我們將直接與一些容器接觸。尤其是,我們將展示如何啟動一個容器,如何使用Dockerfile構建鏡像,如何與注冊服務(registries)打交道,并介紹數據卷(data volumes)的基本概念

啟動容器

在啟動一個容器之前,你需要先從注冊服務中拉取

$ docker pull alpine

啟動容器執行如下簡單命令即可:

$ docker run <image name> <command>

這里的 command 是你想在容器內執行的命令。

如果鏡像本地不存在,Docker嘗試從公共鏡像服務器上取。這個動作是自動執行的,但是你會感受到命令執行的延遲。

需要注意的是在容器內被執行的命令退出后,容器是停止狀態的。例如,你執行的命令是 /bin/echo hello world ,容器啟動,打印"hello word",然后容器停止運行。

例如,執行

$ docker run alpine /bin/echo hello world

你會看類似的如下信息:

$ docker run alpine /bin/echo hello world

Unable to find image 'alpine:latest' locally

latest: Pulling from alpine

31f630c65071: Pull complete

Digest: sha256:074de05bbd8554cf454a19094df34985c8674f54e14474731427a2a31d1970ec

Status: Downloaded newer image for alpine:latest

hello world

我們在容器內啟動 Alpine Linux ,并且安裝 openssh 用于ash提示。首先,執行如下命令:

$ docker run -t -i alpine /bin/ash

參數 -t, -i 意味著分配一個偽終端,并保持接受標準輸入(STDIN)即使沒有登錄。這使得你可以使用容器像一個傳統的虛擬機一樣,只要ash運行即可。

安裝 openssh 如下:

apk update

apk add openssh

如果我們退出容器,我們在硬盤上所做的改動并沒有儲存到容器上。所以下次啟動容器時,openssh是沒有被安裝的。

如果我們想保存改動,我們需要提交(commit)他們。

$ docker ps

你會看到如下信息:

$ docker ps

CONTAINER ID    IMAGE     COMMAND       CREATED           STATUS2511d433bb01    alpine    "/bin/ash"    44 minutes ago    Up 44 minutes

現在我們可以將改動提交到容器中

$ docker commit 2511d433bb01 my/alpine

這里的 2511d433bb01 是容器ID, my/alpine 是我們的倉庫

可以通過執行下面的命令查看:

docker images

你會看到如下類似信息:

$ docker images

REPOSITORY     TAG        IMAGE ID         CREATED             VIRTUAL SIZE

my/alpine      latest     2511d433bb01     About a minute ago  9.501 MB

使用Dockerfiles構建鏡像

在運行容器上提交改動對于試驗來說是可以的。但是在生產場景,使用Dockerfiles來記錄必要的命令是更好的,作為 docker build 命令說明的Dockerfiles可以被納入Git中進行版本控制跟蹤。Docker守護進程(Docker daemon)依次執行你的命令,必要的話提交改動到新鏡像,最終輸出新鏡像ID

創建Dockerfiles,并且執行如下命令:

# base image

FROM alpine

grab ca-certificates and nginx

RUN apk update && apk add ca-certificates nginx

expose ports 80 and 443

EXPOSE 80 443# start up nginx

CMD ["nginx", "-g", "daemon off;"]

現在我們來構建Docker鏡像:

$ docker build -t mynginx .

-t mynginx 參數指定鏡像名為 mynginx ,現在即可運行它:

$ docker run -p 8080:80 mynginx

-p 8080:80 參數將本機的8080端口映射到容器的80端口。

在瀏覽器中輸入下面網址:

http://<ip_of_your_docker_host>:8080

你將會看到:

我們構建了一個簡單的nginx鏡像!

我們可以使用Alpine Linux作為基礎鏡像。我們安裝了nginx,然后開放了端口80和443。最后我們運行了nginx。使用Alpine Linux的原因是它占用空間很小,這使得nginx鏡像也小很多,同時能夠更快的構建,更快的推送到注冊服務器或者從上面拉取。

想進一步了解Dockerfile的命令,請參考 該文獻

與注冊服務器協作

現在我們知道了如何構建Docker鏡像,下面我們來學習如何將鏡像推送到Docker注冊服務上。

在例子中我們使用 Docker Hub 注冊服務。

你需要注冊一個賬戶才能夠推送Docker鏡像。更多信息請參考 用戶手冊

上一個例子中,我們使用如下命令構建出Docker鏡像:

docker build -t mynginx .

該命令可以構建出Docker鏡像,但是它沒有倉庫名字,只能在構建它的本機使用。

為了把它推送到Docker Hub注冊服務(或者其他私服)上,你需要將你用戶名添加到Docker鏡像名中:

$ docker build -t yourname/mynginx .

在docker push前,要確保你已經執行了 docker login 。該命令將你的連接配置保存在你根目錄的 .dockercfg 文件中。

推送到Docker注冊服務,執行如下命令:

$ docker push yourname/mynginx

從Docker注冊服務中拉取,執行如下命令:

$ docker pull yourname/mynginx

如果你自己搭建了Docker私服,執行命令類似如下:

$ docker push your_registry:5000/mynginx

$ docker pull your_registry:5000/mynginx

數據持久化

Docker容器是無狀態的。然而在某些場景下如使用數據庫,你需要持久化的數據。Docker支持兩種持久化數據的方式:數據卷和數劇卷容器。這兩個我們都將依次介紹。

數據卷

數據卷是經過特殊設計的在一個或者多個容器內的目錄,它可以繞過統一文件系統( Union file system )。

數據卷提供了多個有用的特征,來持久化或者共享數據。

  • 數據卷在容器創建時候初始化。如果容器的基礎鏡像在指定的掛載點含有數據,那些已經存在的數據則會在目錄初始化時被拷貝到新的卷中
  • 數據卷可以在容器間共享或者重用
  • 對于數據卷的改動是直接生效的
  • 數據卷不受鏡像更新的影響,即使這些更新修改了數據卷掛載的路徑
  • 即使容器本身已被刪除數據卷仍然存在

數據卷被設計來用于持久化數據,獨立于容器的生命周期。因此當你在刪除容器的時候,Docker絕不會自動刪除這些卷,同樣也不會垃圾回收那些不被容器所引用的卷。

你可以使用 -v 參數執行 docker run 來添加本機目錄作為數據卷到容器中。 -v 可以被多次使用,來掛載多個數據卷

我們在web應用容器中掛載一個單獨的數據卷如下:

$ docker run -p 8080:80 \

-v /data/share/nginx/html:/usr/share/nginx/html mynginx

上面的命令掛載了一個本機目錄 /data/share/nginx/html 到容器中的 /usr/share/nginx/html 目錄。所有我們放到本機目錄的文件都能立即在容器中看到。

注意:如果路徑 /usr/share/nginx/html 已經在容器鏡像中存在,它的內容將被本機上 /data/share/nginx/html 路徑中的內容所替代,這樣是為了保持掛載操作結果的一致性。

數據卷容器

如果你有一些持久化數據想在容器間共享,或者想在非持久化的容器中使用,最佳實踐是創建一個數據卷容器,然后從容器中掛載數據。這避免了在某些Linux操作系統上掛載本機目錄所導致可能會出現的某些權限問題。

我們來新建一個已命名的共享數據卷容器。可以使用busybox鏡像,因為像postgres等其他官方鏡像也是基于busybox鏡像的。由于這些鏡像都有統一文件系統層,Docker就會只保留這些層的一個副本來節省磁盤空間。

執行如下命令:

$ docker create -v /dbdata --name dbdata busybox true

該命令創建了一個使用busybox基礎鏡像的叫做dbdata的數據卷容器,并創建了數據目錄 /dbdata 。

你可以在其他容器使用 --volumes-from 來掛載 /dbdata 卷。

$ docker run -d --volumes-from dbdata --name postgres postgres

在這個例子中,如果postgres鏡像中也有 /dbdata 的目錄,那么從dbdata容器中掛載數據卷就會隱藏postgres鏡像中 /dbdata 下的文件。結果就是只顯示來自dbdata容器對應目錄下的文件。

你可以使用多個 --volumes-from 參數將來自多個容器的多個數據卷整合到一起。

如果你刪除了掛載數據卷的容器,包括初始的dbdata容器,這些數據卷將不會被刪除。為了將數據卷從硬盤刪除,你必須在最后一個引用該數據卷的容器中顯式地執行 docker rm -v 。這使得你可以升級或者有效地在容器間聚合數據。

結論

在本迷你系列的 第一章 中,我們對Docker有了一個整體的認識,什么使得Docker如此特別,它的架構組成。在本文我們學習了構建鏡像,啟動容器,分層的文件系統和如何持久化數據。

請繼續期待我們下一章關于Kubernetes的介紹。

原文鏈接: Docker Overview, Part Two (翻譯:姜俊厚)

來源:http://dockone.io/article/1205

 本文由用戶 yoqz3865 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!