Docker學習總結之Run命令介紹

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

  在使用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總起來講分爲兩類:git

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時能夠設定的資源以下:redis

* 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窗口,來執行信號中斷。這一切都是能夠配置的:docker

-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默認會掛載全部標準數據流,包括輸入輸出和錯誤。你能夠特別指定掛載哪一個標準流。shell

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

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

  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:centos

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內禁用安全策略:bash

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 sven@10.10.10.20:/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 sven@10.10.10.20:/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
sven@10.10.10.20’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/redisclih REDIS_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」來覆蓋默認的工做目錄。

相關文章
相關標籤/搜索