Docker run 命令的使用方法

【編者的話】在Docker中,run應該是用戶使用最多的命令了,不少讀者反饋不是很明白run命令的用法,並且相關的書籍、中文資料中對run命令的描述也不是很是完整,因此DockerOne組織翻譯了Docker官方的文檔,以饗讀者。注意,本文基於最新的Docker 1.4文檔翻譯。


Docker會在隔離的容器中運行進程。當運行  docker run命令時,Docker會啓動一個進程,併爲這個進程分配其獨佔的文件系統、網絡資源和以此進程爲根進程的進程組。在容器啓動時, 鏡像可能已經定義了要運行的二進制文件、暴露的網絡端口等,可是用戶能夠經過 docker run命令從新定義(譯者注:docker run能夠控制一個容器運行時的行爲,它能夠覆蓋 docker build在構建鏡像時的一些默認配置),這也是爲何 run命令相比於其它命令有如此多的參數的緣由。

命令格式

最基本的 docker run命令的格式以下:
 
  
若是須要查看[OPTIONS]的詳細使用說明,請參考Docker關於OPTIONS的 章節。這裏僅簡要介紹Run所使用到的參數。OPTIONS總起來講能夠分爲兩類:
  1. 設置運行方式:
    • 決定容器的運行方式,前臺執行仍是後臺執行;
    • 設置containerID;
    • 設置網絡參數;
    • 設置容器的CPU和內存參數;
    • - 設置權限和LXC參數;
  2. 設置鏡像的默認資源,也就是說用戶可使用該命令來覆蓋在鏡像構建時的一些默認配置。

docker run [OPTIONS]可讓用戶徹底控制容器的生命週期,並容許用戶覆蓋執行 docker build時所設定的參數,甚至也能夠修改自己由Docker所控制的內核級參數。

Operator exclusive options

當執行 docker run時能夠設置如下參數:
  • Detached vs Foreground
    • Detached (-d)
    • - Foreground
  • Container Identification
    • Name (--name)
    • - PID Equivalent
  • IPC Setting
  • Network Settings
  • Clean Up (--rm)
  • Runtime Constraints on CPU and Memory
  • Runtime Privilege, Linux Capabilities, and LXC Configuration

接下來咱們依次進行介紹。

Detached vs foreground

當咱們啓動一個容器時,首先須要肯定這個容器是運行在前臺仍是運行在後臺。
 
  

Detached (-d)

若是在 docker run後面追加 -d=true或者 -d,那麼容器將會運行在後臺模式。此時全部I/O數據只能經過網絡資源或者共享卷組來進行交互。由於容器再也不監聽你執行 docker run的這個終端命令行窗口。但你能夠經過執行 docker attach來從新附着到該容器的回話中。須要注意的是,容器運行在後臺模式下,是不能使用 --rm選項的。

Foregroud
在前臺模式下(不指定 -d參數便可),Docker會在容器中啓動進程,同時將當前的命令行窗口附着到容器的標準輸入、標準輸出和標準錯誤中。也就是說容器中全部的輸出均可以在當前窗口中看到。甚至它均可以虛擬出一個TTY窗口,來執行信號中斷。這一切都是能夠配置的:
 
  

若是在執行run命令時沒有指定 -a參數,那麼Docker默認會掛載全部標準數據流,包括輸入輸出和錯誤,你能夠單獨指定掛載哪一個標準流。
 
  

若是要進行交互式操做(例如Shell腳本),那咱們必須使用 -i -t參數同容器進行數據交互。可是當經過管道同容器進行交互時,就不須要使用 -t參數,例以下面的命令:
 
  

容器識別

Name(--name)

能夠經過三種方式爲容器命名:
  
1. 使用UUID長命名("f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778")
2. 使用UUID短命令("f78375b1c487")
3. 使用Name("evil_ptolemy")

這個UUID標示是由Docker deamon生成的。若是你在執行 docker run時沒有指定 --name,那麼deamon會自動生成一個隨機字符串UUID。可是對於一個容器來講有個name會很是方便,當你須要鏈接其它容器時或者相似須要區分其它容器時,使用容器名稱能夠簡化操做。不管容器運行在前臺或者後臺,這個名字都是有效的。

PID equivalent

若是在使用Docker時有自動化的需求,你能夠將containerID輸出到指定的文件中(PIDfile),相似於某些應用程序將自身ID輸出到文件中,方便後續腳本操做。
 
  
Image[:tag]

當一個鏡像的名稱不足以分辨這個鏡像所表明的含義時,你能夠經過tag將版本信息添加到run命令中,以執行特定版本的鏡像。例如:  docker run ubuntu:14.04

IPC Settings

默認狀況下,全部容器都開啓了IPC命名空間。
 
  

IPC(POSIX/SysV IPC)命名空間提供了相互隔離的命名共享內存、信號燈變量和消息隊列。

共享內存能夠提升進程數據的交互速度。共享內存通常用在數據庫和高性能應用(C/OpenMPI、C++/using boost libraries)上或者金融服務上。若是須要容器中部署上述類型的應用,那麼就應該在多個容器直接使用共享內存了。

Network settings

默認狀況下,全部的容器都開啓了網絡接口,同時能夠接受任何外部的數據請求。
 
  
你能夠經過 docker run --net none來關閉網絡接口,此時將關閉全部網絡數據的輸入輸出,你只能經過STDIN、STDOUT或者files來完成I/O操做。默認狀況下,容器使用主機的DNS設置,你也能夠經過 --dns來覆蓋容器內的DNS設置。同時Docker爲容器默認生成一個MAC地址,你能夠經過 --mac-address 12:34:56:78:9a:bc來設置你本身的MAC地址。

Docker支持的網絡模式有:
  • none。關閉容器內的網絡鏈接
  • bridge。經過veth接口來鏈接容器,默認配置。
  • host。容許容器使用host的網絡堆棧信息。 注意:這種方式將容許容器訪問host中相似D-BUS之類的系統服務,因此認爲是不安全的。
  • container。使用另一個容器的網絡堆棧信息。   
    None模式

將網絡模式設置爲none時,這個容器將不容許訪問任何外部router。這個容器內部只會有一個loopback接口,並且不存在任何能夠訪問外部網絡的router。

Bridge模式

Docker默認會將容器設置爲bridge模式。此時在主機上面將會存在一個docker0的網絡接口,同時會針對容器建立一對veth接口。其中一個veth接口是在主機充當網卡橋接做用,另一個veth接口存在於容器的命名空間中,而且指向容器的loopback。Docker會自動給這個容器分配一個IP,而且將容器內的數據經過橋接轉發到外部。

Host模式

當網絡模式設置爲host時,這個容器將徹底共享host的網絡堆棧。host全部的網絡接口將徹底對容器開放。容器的主機名也會存在於主機的hostname中。這時,容器全部對外暴露的端口和對其它容器的鏈接,將徹底失效。

Container模式

當網絡模式設置爲Container時,這個容器將徹底複用另一個容器的網絡堆棧。同時使用時這個容器的名稱必需要符合下面的格式:--net container:<name|id>.

好比當前有一個綁定了本地地址localhost的Redis容器。若是另一個容器須要複用這個網絡堆棧,則須要以下操做:
 
  

管理/etc/hosts
/etc/hosts文件中會包含容器的hostname信息,咱們也可使用 --add-host這個參數來動態添加/etc/hosts中的數據。
 
  
Clean up (--rm)

默認狀況下,每一個容器在退出時,它的文件系統也會保存下來,這樣一方面調試會方便些,由於你能夠經過查看日誌等方式來肯定最終狀態。另一方面,你也能夠保存容器所產生的數據。可是當你僅僅須要短暫的運行一個容器,而且這些數據不須要保存,你可能就但願Docker能在容器結束時自動清理其所產生的數據。

這個時候你就須要--rm這個參數了。 注意:--rm 和 -d不能共用!
 
  
Security configuration
 
  

你能夠經過 --security-opt修改容器默認的schema標籤。好比說,對於一個MLS系統來講(譯者注:MLS應該是指Multiple Listing System),你能夠指定MCS/MLS級別。使用下面的命令能夠在不一樣的容器間分享內容:
 
  
若是是MLS系統,則使用下面的命令:
 
  
使用下面的命令能夠在容器內禁用安全策略:
 
  
若是你須要在容器內執行更爲嚴格的安全策略,那麼你能夠爲這個容器指定一個策略替代,好比你可使用下面的命令來指定容器只監聽Apache端口:
 
  
注意:此時,你的主機環境中必須存在一個名爲svirt_apache_t的安全策略。

Runtime constraints on CPU and memory

下面的參數能夠用來調整容器內的性能。
 
  
經過 docker run -m能夠調整容器所使用的內存資源。若是主機支持swap內存,那麼可使用 -m能夠設定比主機物理內存還大的值。

一樣,經過 -c能夠調整容器的CPU優先級。默認狀況下,全部的容器擁有相同的CPU優先級和CPU調度週期,但你能夠經過Docker來通知內核給予某個或某幾個容器更多的CPU計算週期。

好比,咱們使用 -c或者 --cpu-shares =0啓動了C0、C一、C2三個容器,使用-c/--cpu-shares=512啓動了C3容器。這時,C0、C一、C2能夠100%的使用CPU資源(1024),但C3只能使用50%的CPU資源(512)。若是這個主機的操做系統是時序調度類型的,每一個CPU時間片是100微秒,那麼C0、C一、C2將徹底使用掉這100微秒,而C3只能使用50微秒。

Runtime privilege, Linux capabilities, and LXC configuration
 
  
默認狀況下,Docker的容器是沒有特權的,例如不能在容器中再啓動一個容器。這是由於默認狀況下容器是不能訪問任何其它設備的。可是經過"privileged",容器就擁有了訪問任何其它設備的權限。

當操做者執行 docker run --privileged時,Docker將擁有訪問主機全部設備的權限,同時Docker也會在apparmor或者selinux作一些設置,使容器能夠容易的訪問那些運行在容器外部的設備。你能夠訪問 Docker博客來獲取更多關於--privileged的用法。

同時,你也能夠限制容器只能訪問一些指定的設備。下面的命令將容許容器只訪問一些特定設備:
 
  
  默認狀況下,容器擁有對設備的讀、寫、建立設備文件的權限。使用 :rwm來配合 --device,你能夠控制這些權限。
 
  
使用 --cap-add--cap-drop,配合 --privileged,你能夠更細緻的控制人哦怒氣。默認使用這兩個參數的狀況下,容器擁有一系列的內核修改權限,這兩個參數都支持 all值,若是你想讓某個容器擁有除了MKNOD以外的全部內核權限,那麼能夠執行下面的命令:
 
  
若是須要修改網絡接口數據,那麼就建議使用 --cap-add=NET_ADMIN,而不是使用 --privileged
 
  
若是要掛載一個FUSE文件系統,那麼就須要 --cap-add--device了。
 
  
若是Docker守護進程在啓動時選擇了 lxc lxc-driver( docker -d --exec-driver=lxc),那麼就可使用 --lxc-conf來設定LXC參數。但須要注意的是,將來主機上的Docker deamon有可能不會使用LXC,因此這些參數有可能會包含一些沒有實現的配置功能。這意味着,用戶在操做這些參數時必需要十分熟悉LXC。

特別注意:當你使用 --lxc-conf修改容器參數後,Docker deamon將再也不管理這些參數,那麼用戶必須自行進行管理。好比說,你使用 --lxc-conf修改了容器的IP地址,那麼在/etc/hosts裏面是不會自動體現的,須要你自行維護。

Overriding Dockerfile image defaults

  當開發者使用 Dockerfile進行build或者使用commit提交容器時,開發人員能夠設定一些鏡像默認參數。

這些參數中,有四個是沒法被覆蓋的:FROM、MAINTAINER、RUN和ADD,其他參數均可以經過 docker run進行覆蓋。咱們將介紹如何對這些參數進行覆蓋。
  • CMD (Default Command or Options)
  • ENTRYPOINT (Default Command to Execute at Runtime)
  • EXPOSE (Incoming Ports)
  • ENV (Environment Variables)
  • VOLUME (Shared Filesystems)
  • USER
  • WORKDIR   

CMD (default command or options)
 
  

這個命令中的COMMAND部分是可選的。由於這個IMAGE在build時,開發人員可能已經設定了默認執行的命令。做爲操做人員,你可使用上面命令中新的command來覆蓋舊的command。

若是鏡像中設定了ENTRYPOINT,那麼命令中的CMD也能夠做爲參數追加到ENTRYPOINT中。

ENTRYPOINT (default command to execute at runtime)
 
  

這個ENTRYPOINT和COMMAND相似,它指定了當容器執行時,須要啓動哪些進程。相對COMMAND而言,ENTRYPOINT是很難進行覆蓋的,這個ENTRYPOINT可讓容器設定默認啓動行爲,因此當容器啓動時,你能夠執行任何一個二進制可執行程序。你也能夠經過COMMAND爲ENTRYPOINT傳遞參數。但當你須要在容器中執行其它進程時,你就能夠指定其它ENTRYPOINT了。

下面就是一個例子,容器能夠在啓動時自動執行Shell,而後啓動其它進程。
 
  
 EXPOSE (incoming ports)

  Dockefile在網絡方面除了提供一個EXPOSE以外,沒有提供其它選項。下面這些參數能夠覆蓋Dockefile的expose默認值:
 
  
  --expose可讓容器接受外部傳入的數據。容器內監聽的端口不須要和外部主機的端口相同。好比說在容器內部,一個HTTP服務監聽在80端口,對應外部主機的端口就多是49880.

  若是使用 -p或者 -P,那麼容器會開放部分端口到主機,只要對方能夠鏈接到主機,就能夠鏈接到容器內部。當使用 -P時,Docker會在主機中隨機從49153 和65535之間查找一個未被佔用的端口綁定到容器。你可使用 docker port來查找這個隨機綁定端口。

當你使用 --link方式時,做爲客戶端的容器能夠經過私有網絡形式訪問到這個容器。同時Docker會在客戶端的容器中設定一些環境變量來記錄綁定的IP和PORT。

ENV (environment variables)
 
  

當容器啓動時,會自動在容器中初始化這些變量。

操做人員能夠經過 -e來設定任意的環境變量,甚至覆蓋已經存在的環境變量,或者是在Dockerfile中經過ENV設定的環境變量。
 
  
操做人員能夠經過 -h來設定hostname。也可使用"--link name:alias"來設定環境變量,當使用 --link後,Docker將根據後面提供的IP和PORT信息來鏈接服務端容器。下面就是使用redis的例子:
 
  
你使用 --link後,就能夠獲取到關於Redis容器的相關信息。
 
  
Docker也會將這個alias的IP地址寫入到/etc/hosts文件中。而後你就能夠經過別名來訪問link後的容器。
 
  
若是你重啓了源容器(servicename),相關聯的容器也會同步更新/etc/hosts。

VOLUME (shared filesystems)
 
  

關於volume參數,能夠在 Managing data in containers查看詳細說明,須要注意的是開發人員能夠在Dockerfile中設定多個volume,可是隻能由運維人員設置容器直接的volume訪問。

USER

容器中默認的用戶是root,可是開發人員建立新的用戶以後,這些新用戶也是可使用的。開發人員能夠經過Dockerfile的USER設定默認的用戶,並經過"-u "來覆蓋這些參數。

 WORKDIR

容器中默認的工做目錄是根目錄(/)。開發人員能夠經過Dockerfile的WORKDIR來設定默認工做目錄,操做人員能夠經過"-w"來覆蓋默認的工做目錄。

原文連接: Docker run reference(譯者:vikings 審校:李穎傑)
相關文章
相關標籤/搜索