Docker學習總結之Run命令介紹

Docker學習總結之Run命令介紹
本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原創,轉載請標明.謝謝!

  在使用Docker時,執行最多的命令某過於run了。這個命令可以說是所有docker操作的入口。在Docker官方Reference中單獨列出了一個章節來介紹Run的各種參數使用,也足以看出Docker run的重要性。有感於此,我感覺有必要好好學習一下Run命令,因此特意看了一下Run命令介紹,結合日常中的使用心得,分享一下。以下文檔大部分翻譯於Docker 官方Reference,肯定會存在不少錯誤之處,希望能拋磚引玉,大家共同討論。
  Docker在執行時會將相關進程封裝到相互隔離的容器(container)中。當執行 docker run時,Docker會啓動一個進程,同時給這個進程分配其獨佔的文件系統,獨佔的網絡資源和以此進程爲根進程的進程組。在Docker啓動container時加載的Image,或許已經定義好了默認的啓動進程,需要exposer的網絡端口和其他在Dockerfile中定義好的資源。但使用docker run 都可以重新對這個image進行默認定義。這就是爲什麼run命令參數比docker其他命令參數都多的原因。
  最基本的docker run命令是如下格式:
$ sudo docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG…]
  如果需要查看[OPTIONS]的詳細使用說明,請參考Docker關於OPTIONS的說明。這裏僅簡要介紹Run所使用到的參數。
  OPTIONS總起來說分爲兩類:

1. 設定操作執行方式:設定image的默認資源,也就是image使用者可以用此命令來覆蓋image開發者在build階段所設定的默認值docker run [OPTIONS]可以讓image使用者完全控制container的生命週期,允許image使用者覆蓋所有image開發者在執行docker build時所設定的參數,甚至也可以修改本身由Docker所控制的內核級參數。
    1. 決定container的運行方式,前臺執行還是後臺執行設定containerID設定network參數設定container的CPU和Memory參數設定權限(Privileges )和LXC參數

Operator exclusive options  當執行docker run時可以設定的資源如下:

* Detached vs ForegroundContainer IdentificationIPC SettingNetwork SettingsClean Up (--rm)Runtime Constraints on CPU and MemoryRuntime Privilege, Linux Capabilities, and LXC Configuration

  我們依次進行介紹。
  Detached vs foreground  當我們啓動一個container時,首先需要確定這個container是運行在前臺模式還是運行在後臺模式。
-d=false: Detached mode: Run container in the background, print new container id
  Detached (-d)  如果在docker run 後面追加-d=true或者-d,則containter將會運行在後臺模式(Detached mode)。此時所有I/O數據只能通過網絡資源或者共享卷組來進行交互。因爲container不再監聽你執行docker run的這個終端命令行窗口。但你可以通過執行docker attach 來重新掛載這個container裏面。需要注意的時,如果你選擇執行-d使container進入後臺模式,那麼將無法配合”–rm”參數。
  Foregroud
  如果在docker run後面沒有追加-d參數,則container將默認進入前臺模式(Foregroud mode)。Docker會啓動這個container,同時將當前的命令行窗口掛載到container的標準輸入,標準輸出和標準錯誤中。也就是container中所有的輸出,你都可以再當前窗口中查看到。甚至docker可以虛擬出一個TTY窗口,來執行信號中斷。這一切都是可以配置的:

-a=[]      : Attach to STDIN, STDOUT and/or STDERR
-t=false    : Allocate a pseudo-tty
–sig-proxy=true : Proxify all received signal to the process (non-TTY mode only)
-i=false    : Keep STDIN open even if not attached
  如果在執行run命令時沒有指定-a,那麼docker默認會掛載所有標準數據流,包括輸入輸出和錯誤。你可以特別指定掛載哪個標準流。

$ sudo docker run -a stdin -a stdout -i -t ubuntu /bin/bash (只掛載標準輸入輸出)

  對於執行容器內的交互式操作,例如shell腳本。我們必須使用 -i -t來申請一個控制檯同容器進行數據交互。但是當通過管道同容器進行交互時,就不能使用-t. 例如下面的命令
echo test | docker run -i busybox cat
  Container identification  Name (–name)  給container命名有三種方式:

  1. 使用UUID長命名(“f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778”)
  2. 使用UUID短命令(“f78375b1c487”)
  3. 使用Name(“evil_ptolemy”)
  這個UUID標示是由Docker deamon來生成的。如果你在執行docker run時沒有指定 –name,那麼deamon會自動生成一個隨機數字符串當做UUID。但是對於一個container來說有個name會非常方便,因爲你可以當你需要link其它容器時或者其他類似需要區分其它容器時,使用容器名稱會簡化操作。無論container運行在前臺或者後臺,這個名字都是有效的。
  PID equivalent  當你在運行docker時有自動化的要求,那麼你可以要求Docker將containerID 輸出到你指定的文件中(PIDfile).這種行爲就類似於有些應用程序將自身ID輸出到文件中,方便後續腳本操作。
–cidfile=”“: Write the container ID to the file
  Image[:tag]  當一個image的名稱不足以分辨這個image所代表的含義時,你可以通過tag將版本信息添加到run 命令中來執行特定版本的image。例如: docker run ubuntu:14.04
 IPC Settings  默認情況下,所有容器都開啓了IPC命名空間。
–ipc=”” : Set the IPC mode for the container,
‘container:

docker run –security-opt label:level:s0:c100,c200 -i -t fedora bash

  如果是MLS系統,則使用下面的命令:

docker run –security-opt label:level:TopSecret -i -t rhel7 bash

  使用下面的命令可以在container內禁用安全策略:

docker run –security-opt label:disable -i -t fedora bash

  如果你需要在container內執行更爲嚴格的安全策略,那麼你可以爲這個container指定一個策略替代。比如你可以使用下面的命令來指定container只允許監聽apache port

docker run –security-opt label:type:svirt_apache_t -i -t centos bash

  注意:此時,在你的host環境中必須存在一個名爲svirt_apache_t的安全策略。
  
 Runtime constraints on CPU and memory  下面的參數可以用來調整container內的性能參數。
-m=”“: Memory limit (format: , where unit = b, k, m or g)
-c=0 : CPU shares (relative weight)
  通過docker run -m 可以很方便的調整container所使用的內存資源。如果host支持swap內存,那麼使用-m可以設定比host物理內存還大的值。
  同樣,通過-c 可以調整container的cpu優先級。默認情況下,所有的container享有相同的cpu優先級和cpu調度週期。但你可以通過Docker來通知內核給予某個或某幾個container更多的cpu計算週期。
  默認情況下,使用-c或者–cpu-shares 參數值爲0,可以賦予當前活動container 1024個cpu共享週期。這個0值可以針對活動的container進行修改來調整不同的cpu循環週期。
  比如,我們使用-c或者–cpu-shares =0啓動了C0,C1,C2三個container,使用-c/–cpu-shares=512啓動了C3.這時,C0,C1,C2可以100%的使用CPU資源(1024),但C3只能使用50%的CPU資源(512)。如果這個host的OS是時序調度類型的,每個CPU時間片是100微秒,那麼C0,C1,C2將完全使用掉這100微秒,而C3只能使用50微秒。
 Runtime privilege, Linux capabilities, and LXC configuration
–cap-add: Add Linux capabilities
–cap-drop: Drop Linux capabilities
–privileged=false: Give extended privileges to this container
–device=[]: Allows you to run devices inside the container without the –privileged flag.
–lxc-conf=[]: (lxc exec-driver only) Add custom lxc options –lxc-conf=”lxc.cgroup.cpuset.cpus = 0,1”
  默認情況下,Docker的container是沒有特權的。例如不能再container裏面再啓動一個container。這是因爲默認情況下container是不能訪問任何其他設備的。但是通過”privileged”,container就擁有了訪問任何其他設備的權限。
  當操作者執行docker run –privileged時,Docker將擁有訪問host所有設備的權限,同時Docker也會在apparmor或者selinux做一些設置,使container可以容易的訪問那些運行在container外部的設備。你可以訪問Docker blog來獲取更多關於–privileged的用法。
  同時,你也可以限制container只能訪問一些指定的設備。下面的命令將允許container只訪問一些特定設備:
$ sudo docker run –device=/dev/snd:/dev/snd …
  默認情況下,container擁有對設備的讀,寫,創建設備文件的權限。使用:rwm來配合–device,你可以控制這些權限。

  $ sudo docker run –device=/dev/sda:/dev/xvdc –rm -it ubuntu fdisk /dev/xvdc

Command (m for help): q
$ sudo docker run --device=/dev/sda:/dev/xvdc:r --rm -it ubuntu fdisk  /dev/xvdc
You will not be able to write the partition table.

Command (m for help): q

$ sudo docker run --device=/dev/sda:/dev/xvdc:w --rm -it ubuntu fdisk  /dev/xvdc
    crash....

$ sudo docker run --device=/dev/sda:/dev/xvdc:m --rm -it ubuntu fdisk  /dev/xvdc
fdisk: unable to open /dev/xvdc: Operation not permitted

  使用–cap-add和–cap-drop,配合–privileged,你可以更細緻的控制container。默認使用這兩個參數的情況下,container擁有一系列的內核修改權限。這兩個參數都支持all值,如果你想讓某個container擁有除了MKNOD之外的所有內核權限,那麼可以執行下面的命令:
sudodockerruncapadd=ALLcapdrop=MKNOD  使capadd=NETADMIN使privileged docker run -t -i –rm ubuntu:14.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
dockerruntirmcapadd=NETADMINubuntu:14.04iplinkadddummy0typedummy  FUSEcapadddevice docker run –rm -it –cap-add SYS_ADMIN sshfs sshfs [email protected]:/home/sven /mnt
fuse: failed to open /dev/fuse: Operation not permitted
dockerrunrmitdevice/dev/fusesshfssshfssven@10.10.10.20:/home/sven/mntfusermount:mountfailed:Operationnotpermitted docker run –rm -it –cap-add SYS_ADMIN –device /dev/fuse sshfs

sshfs [email protected]:/home/sven /mnt

The authenticity of host ‘10.10.10.20 (10.10.10.20)’ can’t be established.
ECDSA key fingerprint is 25:34:85:75:25:b0:17:46:05:19:04:93:b5:dd:5f:c6.
Are you sure you want to continue connecting (yes/no)? yes
[email protected]’s password:
root@30aa0cfaf1b5:/# ls -la /mnt/src/docker
total 1516
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:08 .
drwxrwxr-x 1 1000 1000 4096 Dec 4 11:46 ..
-rw-rw-r– 1 1000 1000 16 Oct 8 00:09 .dockerignore
-rwxrwxr-x 1 1000 1000 464 Oct 8 00:09 .drone.yml
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:11 .git
-rw-rw-r– 1 1000 1000 461 Dec 4 06:08 .gitignore
  如果docker啓動時選擇了lxc-driver,(docker -d –exec-driver=lxc)。那麼就可以使用–lxc-conf來設定LXC參數。但需要注意的是,未來host上面的docker deamon有可能不會使用LXC,所以這些參數有可能會包含一些沒有實現的配置功能。那麼意味着,操作者在操作這些參數時必須要十分熟悉LXC。
  特別注意:當你使用–lxc-conf修改container參數後,docker deamon將不再管理這些參數,那麼必須由操作者自行進行管理。比如說,你使用–lxc-conf修改了container的IP地址,那麼在/etc/hosts裏面是不會自動體現的,需要你自行維護。
 Overriding Dockerfile image defaults  當開發者使用Dockerfile進行build或者使用commit提交container時,開發人員可以設定一些image默認參數。
  這些參數中,有四個是無法被覆蓋的: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)USERWORKDIR

  
 CMD (default command or options)  
$ sudo docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG…]
  這條命令中的COMMAND部分是可選的。因爲這個IMAGE在build時,開發人員可能已經設定了默認執行的command。作爲操作人員,你可以使用上面命令中新的command來覆蓋舊的command。
  如果image中設定了ENTRYPOINT,那麼命令中的CMD也可以作爲參數追加到ENTRYPOINT中。

 ENTRYPOINT (default command to execute at runtime)
–entrypoint=”“: Overwrite the default entrypoint set by the image
  這個ENTRYPOINT和COMMAND類似,它指定了當container執行時,需要啓動哪些進程。相對COMMAND而言,ENTRYPOINT是比較困難進行覆蓋的,這個ENTRYPOINT可以讓container設定默認啓動行爲,所以當container啓動時,你可以執行任何一個二進制可執行程序。你也可以通過COMMAND給這個ENTRYPOINT傳遞參數。但當你需要再container中執行其他進程時,你就可以指定其他ENTRYPOINT了。
  下面就是一個例子,container可以在啓動時自動執行shell,然後啓動其它進程。
$ sudo docker run -i -t –entrypoint /bin/bash example/redis

or two examples of how to pass more parameters to that ENTRYPOINT:

sudodockerrunitentrypoint/bin/bashexample/redisclsl sudo docker run -i -t –entrypoint /usr/bin/redis-cli example/redis –help
  
 EXPOSE (incoming ports)  Dockefile在網絡方面除了提供一個EXPOSE之外,沒有提供其它選項。下面這些參數可以覆蓋Dockefile的expose默認值:
–expose=[]: Expose a port or a range of ports from the container
without publishing it to your host
-P=false : Publish all exposed ports to the host interfaces
-p=[] : Publish a container᾿s port to the host (format:
ip:hostPort:containerPort | ip::containerPort |
hostPort:containerPort | containerPort)
(use ‘docker port’ to see the actual mapping)
–link=”” : Add link to another container (name:alias)
  –expose可以讓container接受外部傳入的數據。container內監聽的port不需要和外部host的port相同。比如說在container內部,一個HTTP服務監聽在80端口,對應外部host的port就可能是49880.
  操作人員可以使用–expose,讓新的container訪問到這個container。具體有三個方式:
  1. 使用-p來啓動container。
  2. 使用-P來啓動container。
  3. 使用–link來啓動container。
  如果使用-p或者-P,那麼container會開發部分端口到host,只要對方可以連接到host,就可以連接到container內部。當使用-P時,docker會在host中隨機從49153 和65535之間查找一個未被佔用的端口綁定到container。你可以使用docker port來查找這個隨機綁定端口。
  當你使用–link方式時,作爲客戶端的container可以通過私有網絡形式訪問到這個container。同時Docker會在客戶端的container中設定一些環境變量來記錄綁定的IP和PORT。
  
 ENV (environment variables)VariableValueHOMESet based on the value of USERHOSTNAMEThe hostname associated with the containerPATHIncludes popular directories, such as :
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binTERMxterm if the container is allocated a psuedo-TTY   當container啓動時,會自動在container中初始化這些變量。
  操作人員可以通過-e來設定任意的環境變量。甚至覆蓋已經存在的環境變量,或者是在Dockerfile中通過ENV設定的環境變量。
  
$ sudo docker run -e “deep=purple” –rm ubuntu /bin/bash -c export
declare -x HOME=”/”
declare -x HOSTNAME=”85bc26a0e200”
declare -x OLDPWD
declare -x PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
declare -x PWD=”/”
declare -x SHLVL=”1”
declare -x container=”lxc”
declare -x deep=”purple”

  操作人員可以通過-h來設定hostname。也可以使用”–link name:alias”來設定環境變量,當使用–link後,docker將根據後面提供的IP和PORT信息來連接服務端container。下面就是使用redis的例子:

Start the service container, named redis-name

$ sudo docker run -d –name redis-name dockerfiles/redis
4241164edf6f5aca5b0e9e4c9eccd899b0b8080c64c0cd26efe02166c73208f3

The redis-name container exposed port 6379

sudodockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES4241164edf6f dockerfiles/redis:latest /redis-stable/src/re 5 seconds ago Up 4 seconds 6379/tcp redis-name

Note that there are no public ports exposed since we didn᾿t use -p or -P

sudodockerport4241164edf6f63792014/01/2500:55:38Error:Nopublicport6379publishedfor4241164edf6f  使linkRedisContainer sudo docker run –rm –link redis-name:redis_alias –entrypoint /bin/bash dockerfiles/redis -c export
declare -x HOME=”/”
declare -x HOSTNAME=”acda7f7b1cdc”
declare -x OLDPWD
declare -x PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
declare -x PWD=”/”
declare -x REDIS_ALIAS_NAME=”/distracted_wright/redis”
declare -x REDIS_ALIAS_PORT=”tcp://172.17.0.32:6379”
declare -x REDIS_ALIAS_PORT_6379_TCP=”tcp://172.17.0.32:6379”
declare -x REDIS_ALIAS_PORT_6379_TCP_ADDR=”172.17.0.32”
declare -x REDIS_ALIAS_PORT_6379_TCP_PORT=”6379”
declare -x REDIS_ALIAS_PORT_6379_TCP_PROTO=”tcp”
declare -x SHLVL=”1”
declare -x container=”lxc”

And we can use that information to connect from another container as a client:

sudodockerrunitrmlinkredisname:redisaliasentrypoint/bin/bashdockerfiles/redisc/redisstable/src/redisclihREDIS_ALIAS_PORT_6379_TCP_ADDR -p REDISALIASPORT6379TCPPORT172.17.0.32:6379>  DockeraliasIP/etc/hostslinkcontainer sudo docker run -d –name servicename busybox sleep 30
$ sudo docker run -i -t –link servicename:servicealias busybox ping -c 1 servicealias
  如果你重啓了源container(servicename),相關聯的container也會同步更新/etc/hosts。
 VOLUME (shared filesystems)
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro].
If “container-dir” is missing, then docker creates a new volume.
–volumes-from=”“: Mount all volumes from the given container(s)
  關於volume參數,可以再 Managing data in containers 查看詳細說明。需要注意的是開發人員可以在Dockerfile中設定多個volume,但是隻能由操作人員設置container直接的volume訪問。
 USER  container中默認的用戶是root。但是開發人員創建新的用戶之後,這些新用戶也是可以使用的。開發人員可以通過Dockerfile的USER設定默認的用戶,操作人員可以通過”-u “來覆蓋這些參數。
 WORKDIR   container中默認的工作目錄是根目錄(/)。開發人員可以通過Dockerfile的WORKDIR來設定默認工作目錄,操作人員可以通過”-w”來覆蓋默認的工作目錄。

發佈了29 篇原創文章 · 獲贊 4 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章