Docker,系統影分身之術

目錄

  1. Docker安裝
    1.1. Windows
    1.2. Ubuntu
  2. Docker容器的使用
    2.1. 啓動一個新的容器
    2.2. 掛起運行的程序
    2.3. 重啓被掛起的程序
    2.4. 終止容器運行
    2.5. 重新運行已有容器
  3. Docker資源的管理
    3.1. 管理鏡像資源
    3.2. 管理容器資源
    3.3. 管理網絡資源
    3.4. 創建自己的鏡像
  4. References

正文

在我電腦上沒問題啊!

It works on my machine

如果你看懂了上面這句話,說明我們是同道中人。寫程序有四種痛:

  1. 起早摸黑寫好了代碼,在自己的電腦上運行的好好,但是到了另一臺電腦上各種問題層出不窮,軟件越複雜依賴越多,頭就越大;
  2. 想幹一件大事,辛歷盡千辛萬苦配置好了環境,換了電腦又要從頭再來。或者某天無意對電腦做了小小的改動,環境崩了;
  3. 想研究個新技術或者學個新技能,僅僅是搭建環境已經竭盡全力,你還不能確定有沒有遺漏;
  4. 頭髮越來越少。

幸運的是,除了第四點,前三點已經有了解決方案,它就是Docker —— 容器化技術。它可以通過容器來構建、運行和分發應用程序。借用Java的口號就是:一次配置,到處運行。

或許你會問,既然已經有了虛擬機,爲什麼還要搞出個容器?容器化其實就是一種虛擬化技術,與傳統虛擬機相比,它有着輕量、獨立、可伸縮、可移植以及靈活等特點。容器直接運行於內核之上,多個容器共用系統的內核,直接通過內核獲取系統資源,用多少取多少;而虛擬機則通過一個管理程序來獲取宿主系統的資源,運行在其上的程序有着自己的內核,就算你跑的是個Hello World,它也佔用這很大一塊資源。拿吃飯打個比方,容器是按點的菜收錢:你點多少菜付多少錢;虛擬機是按人頭收錢,只要你人在那,就算你只喝了一口水也照樣收你這麼多錢。它的區別如圖1所示。

Fig 1 Container vs VM

當然,我不止一次說過,工具是不分優劣的。某種特定場合下,某個工具更合適,僅此而已。“殺雞焉用牛刀”,說的也不是那種刀比另一種刀更好。這篇文章的主要目的是介紹Docker的用法。

0. Docker簡介

Docker引擎由客戶端(Client)、守護進程(Daemon)和註冊表(Register)三部分組成,如圖2所示。用戶通過客戶端發送命令來管理Docker的資源,包括鏡像、容器、網絡等(鏡像和容器的關係就類似於程序和進程的誒關係);守護進程接收客戶端以及API發過來命令來操縱容器,從而實現鏡像、容器、網絡等資源的管理;而註冊表就是一個倉庫,放着各種各樣的鏡像。因此,使用Docker主要就是使用Docker客戶端命令。

Fig 2 Docker's architecture

Docker客戶端的命令,可以大致分爲三部分,每個部分又可以接着細分:

  1. Docker安裝;
  2. Docker容器的使用;
  3. Docker資源的管理;

1. Docker安裝

安裝原本說是沒有什麼好說的,但是由於在Windows 10上Docker和VirtualBox不能共存,因此還是簡單介紹介紹下。

1.1. Windows

  1. 首先,在Windows下,首先要打開Hyper-V選項,打開方式爲:【控制面板】=>【程序】=>【程序和功能】=>【啓用或關閉Windows功能】,然後勾選Hyper-V及其子選項;

Fig 3 Windows configuration

  1. 接下來,就直接到官網下載安裝Windows版本即可。

值得注意的是,Docker和VirtualBox不能共存,因此你只能二選一。安裝了Docker後,回頭你再想用VirtualBox可能會遇到VT-x is not available (VERR_VMX_NO_VMX)這個錯誤,解決方法如下:

  1. 以管理員身份打開命令提示符;
  2. 輸入bcdedit回車,你看到的應該看到hypervisorlaunchtype的值是auto
  3. 輸入bcdedit /set hypervisorlaunchtype off並回車;
  4. 重啓電腦。

1.2. Ubuntu

在Ubuntu下安裝Docker,依次輸入以下命令即可:

# Commands for install docker on Ubuntu,if command fail, consult [https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
 
# x86_64 / amd64
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
 
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
 
# Test
sudo docker run hello-world

2. Docker容器的使用

Docker使用可分爲以下三個部分:

  1. 啓動新容器;
  2. 掛起一個容器;
  3. 重啓被掛起的容器;
  4. 停止容器;
  5. 重新啓動已有容器

這裏只列舉一些常用的,以及一般場景下夠用的命令。

2.1. 啓動一個新的容器

啓動一個新容器的命令爲docker run,常用命令大致如下:

docker run -it -v <host dir>:<container dir> -w/<container dir> --name <your container name> --rm <your docker image name>

-it表示啓動一個交互式的容器,也就是你可以在命令行輸入命令進行交互;
-v將本地目錄和容器中的一個目錄做映射,這樣在容器中就能直接訪問該目錄下的內容;
-w指定容器啓動後的工作目錄;
--name用於個這個容器分配一個名字,方便表明該容器的目的以及後續管理;
--rm表示當容器退出後自動刪除。
例如:

docker run -it -v `pwd`/docker:/workspace -w/workspace --name ubuntu:16.04 ubuntu:16.04

上面命令中通過ubuntu:16.04這個鏡像創建了一個名叫ubuntu:16.04的容器可交互的。使用docker run的時候,如果本地沒有指定的鏡像,Docker會嘗試從遠程註冊表(倉庫)中尋找,找到後拉取(pull)到本地再創建。

2.2. 掛起運行的程序

docker pause CONTAINER [CONTAINER...]

2.3. 重啓被掛起的程序

docker unpause CONTAINER [CONTAINER...]

2.4. 終止容器運行

如果是交互式的容器,直接輸入exit便退出了容器。如果是非交互式的容器,通過以下命令:

docker stop <container id or name>

有時候容器運行了很久,我都不記得容器名字和ID了,怎麼辦?可以通過以下命令獲取所有容器信息:

docker container ls -a

2.5. 重新運行已有容器

# -i , optional, starting interactive
docker start -i <container id or name>

3. Docker資源的管理

Docker的鏡像和容器的關係,就類似於程序和進程的關係。鏡像是一個只讀文件,它裏面包含了如何創建一個容器的指令和模板;而容器就是一個鏡像的實例。鏡像和容器都是Docker引擎管理的重要資源,此外,還有網絡資源、集羣資源、插件和磁盤資源等。這裏只介紹簡單使用場景下常用的一些管理命令:

  1. 管理鏡像資源;
  2. 管理容器資源;
  3. 管理網絡資源;
  4. 創建自己的鏡像。

其實管理Docker資源的命令和我們一般使用的Linux命令很類似,基本命令構成爲docker <resources type> <linux/git command><resources type>可以是imagecontainernetwork等,而<linux/git command>則可以是lsrmcommit等。例如:

# list local images
docker image ls -a
# remove local images
docker image rm <image id/name>
docker container ls -a 
docker container rm <container id>

實際使用過程中,也可以類似Linux中man COMMAD去查看某個命令用法一樣,可以使用直接使用`docker 查看具體命令的用法,例如:

$ docker network

Usage:  docker network COMMAND

Manage Docker networks

Options:
      --help   Print usage

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

3.1. 管理鏡像資源

  1. 遠程鏡像搜索;
  2. 拉取鏡像到本地;
  3. 本地鏡像查看;
  4. 本地鏡像移除。

我們使用Docker的時候,首先,可以向看看本地有沒有我們想要的鏡像:

docker images # or docker image ls -a

如果本地沒有,可以使用以下命令搜索註冊表上有沒有我們想要的:

docker search [OPTIONS] TERM
# 例如:docker search ubuntu

搜索出來所有可用的鏡像後選擇自己想要的,拉取到本地:

docer pull <image name>
# 例如:docker pull ubuntu:16.04

其實,當我們直接使用docker run的時候,docker run就是首先執行上面三步。

當有些鏡像我們不再需要了,我們可以刪除

docker image rm <image id/name>

3.2. 管理容器資源

與鏡像資源類似,對容器的管理也是類似的:

  1. 查看已有容器;
  2. 刪除已有容器;
  3. 查看某個容器詳細信息;
  4. 容器的創建、暫停、重新運行等。

查看容器:

docker container ls -a

通過列出的容器,可以獲取到容器的ID或者名字,進而可以刪除容器:

docker container rm <container id/name>

或者,查看容器的詳細信息:

docker container inspect <container id/name>

而對於容器的創建、重啓等操作前面已經介紹過了。

3.3. 管理網絡資源

網絡資源,其實就是專門給容器使用虛擬網絡設備。默認情況下會有個一個名字是brigde的路由器,所有容器如果未經指定都會鏈接到上面,組成一個局域網。對網絡資源的管理可以使用以下命令:
查看已有的網絡資源:

docker network ls

查看某個網絡資源的詳細信息:

docker network inspect <network id/name>

網絡資源的創建和刪除:

docker network create
docket network rm <network id/name>

網絡的鏈接和斷開:

docker network connect <network> <container>
docker network disconnect <network> <container>

3.4. 創建自己的鏡像

Docker相比於虛擬機的優勢,主要就是它能夠很輕易的分享,或者說轉移已經配置好的環境,並且體積相對於整個虛擬可以小很多。這個是怎麼實現的呢?主要有兩種方法:

  1. 將已有容器打包成鏡像,然後推到遠程倉庫;
  2. 在已有的鏡像基礎上,通過Dockerfile中的命令創建一個新的鏡像。

從已有容器打包可以使用以下命令:

docker container commit --author <author name> -m <new image description> <container id/name> <image name>

例如,我運行了一個Ubuntu16.04的容器,併爲它配置了adb(Android Debug Bridge)環境。爲了能在別的機器上使用Ubuntu16.04的時候可以不用再配置adb,我將它打包成了一個新的鏡像,命令和結果顯示如下:

zhou@zhou:~$ docker container commit --author SunnyZhou -m 'Add adb' dbc7bdb56f2a ubuntu_with_adb:16.04
sha256:de247093e26e4e91eb4470d14067cdde094bddb46c063964ff254967282de113
zhou@zhou:~$ docker images
REPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE
ubuntu_with_adb                                16.04               de247093e26e        11 seconds ago      128MB
ubuntu                                         16.04               77be327e4b63        2 months ago        124MB

第二種方法是通過Dockerfile來創建新的容器,一個簡單的例子是,還是創建一個帶adb的Ubuntu16.04:
首先編寫Dockerfile(完整的Dockerfile命令參看文末參考文檔):

FROM ubuntu:16.04                                                           
COPY platform-tools/adb /sbin/adb

然後使用docker build來創建:

zhou@zhou:~/docker$ vi Dockerfile
zhou@zhou:~/docker$ docker build . --tag ubuntu-adb:16.04Sending build context to Docker daemon  26.95MB
Step 1/2 : FROM ubuntu:16.04
 ---> 77be327e4b63
Step 2/2 : COPY platform-tools/adb /sbin/adb
 ---> 1a5e2b476d20
Successfully built 1a5e2b476d20
Successfully tagged ubuntu-adb:16.04

這篇文章知識Docker的一篇概覽,也是我日常使用Docker最多的命令。完整的命令請參看參考文檔。

公衆號二維碼

首發於個人微信公衆號TensorBoy。微信掃描上方二維碼或者微信搜索TensorBoy並關注,及時獲取更多最新文章!
C++ | Python | 推理引擎 | AI框架源碼,有一起玩耍的麼?

References

[1] https://docs.docker.com/engine/reference/commandline/docker/
[2] https://docs.docker.com/get-started/overview/
[3] https://docs.docker.com/docker-for-windows/install/
[4] https://docs.docker.com/engine/reference/builder/#usage
[5] https://github.com/docker/labs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章