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