個人Docker筆記(補全ing)

Introduction

Docker helps developers build and ship higher-quality applications, faster." -- What is Dockerhtml

Reference

Tutorials & Docs

Practices & Resources

Books & Tools

Quick Start

Installation

Ubuntu

  • 經過系統自帶包安裝web

Ubuntu 14.04 版本系統中已經自帶了 Docker 包,能夠直接安裝。mongodb

$ sudo apt-get update
$ sudo apt-get install -y docker.io
$ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
$ sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io

若是使用操做系統自帶包安裝 Docker,目前安裝的版本是比較舊的 0.9.1。 要安裝更新的版本,能夠經過使用 Docker 源的方式。

  • 經過Docker源安裝最新版本

要安裝最新的 Docker 版本,首先須要安裝 apt-transport-https 支持,以後經過添加源來安裝。

$ sudo apt-get install apt-transport-https
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
$ sudo bash -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$ sudo apt-get update
$ sudo apt-get install lxc-docker
  • 14.04 以前版本

若是是較低版本的 Ubuntu 系統,須要先更新內核。

$ sudo apt-get update
$ sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
$ sudo reboot

而後重複上面的步驟便可。

安裝以後啓動 Docker 服務。

$ sudo service docker start

CentOS

Docker 支持 CentOS6 及之後的版本。

  • CentOS6

對於 CentOS6,可使用 EPEL 庫安裝 Docker,命令以下

$ sudo yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm
$ sudo yum install docker-io
  • CentOS7

CentOS7 系統 CentOS-Extras 庫中已帶 Docker,能夠直接安裝:

$ sudo yum install docker

安裝以後啓動 Docker 服務,並讓它隨系統啓動自動加載。

$ sudo service docker start
$ sudo chkconfig docker on

Docker Toolbox(Mac & Windows)

早期在Windows或者MAC環境下使用Docker主要利用的是Boot2Docker這個命令行工具,而Toolbox能夠安裝你在開發中運行Docker時所須要的一切:Docker客戶端、Compose(僅Mac須要)、Kitematic、Machine以及VirtualBox。Toolbox使用Machine和VirtualBox在虛擬機中建立了一個引擎來運行容器。在該虛擬機上,你可使用Docker客戶端、Compose以及Kitematic來運行容器。而Toolbox自己已經能夠取代了Boot2Docker的做用。

Docker的Toolbox主要集成了以下幾個不一樣的工具的集合:

  • Docker Client docker binary

  • Docker Machine docker-machine binary

  • Docker Compose docker-compose binary

  • Kitematic – Desktop GUI for Docker

  • Docker Quickstart Terminal app

以Mac系統爲例,使用Docker Toolbox安裝Docker環境與Linux系統的區別在於,在標準的Linux系統上的安裝中,Docker客戶端、Docker守護進程以及全部的容器都是直接運行在本地的:

而在OS X或者Windows系統的安裝中,Docker的相關的程序是運行在一個內置的小型的Linux虛擬機中的。

這裏能夠下載Toolbox的安裝程序,雙擊打開按照步驟提示安裝好以後,便可以進行下一步,首先在Applications文件夾或者Launchpad中打開Docker QuickStart Terminal,該程序會直接打開一個終端控制檯,而且建立或者鏈接到一個叫default的虛擬機而且將控制檯登陸到該虛擬機中。固然,用戶也能夠用docker-machine命令來手動建立或者登陸到虛擬機中:

From your shell:從命令行建立

  • 建立一個新的Docker虛擬機

$ docker-machine create --driver virtualbox default
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env default

注意,該虛擬機相關的配置文件存放在~/.docker/machine/machines/default目錄下。

  • 列舉全部可用的機器

$ docker-machine ls
NAME                ACTIVE   DRIVER       STATE     URL                         SWARM
default             *        virtualbox   Running   tcp://192.168.99.101:2376
  • 獲取環境配置

$ docker-machine env default
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/mary/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell: 
# eval "$(docker-machine env default)"
  • 鏈接到該虛擬機

$ eval "$(docker-machine env default)"

Proxy & Mirror

Proxy For boot2docker

若是是使用boot2docker配置的Docker的運行環境,那麼配置文件並無放置在Windows或者MAC系統種,而是附着在了小的Linux虛擬機的內核中。首先咱們須要在boot2docker的命令行中進入到VM的設置:

Creating Machine default...
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env default
Starting machine default...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
Setting environment variables for machine default...

. . .

                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/


docker is configured to use the default machine with IP 192.168.99.100
For help getting started, check out the docs at https://docs.docker.com

如今能夠修改 /var/lib/boot2docker/profile 這個文件來設置代理:

docker@boot2docker:~$ sudo vi /var/lib/boot2docker/profile

Tinycore 須要按照以下格式進行配置: protocol://ip:port

安全起見我同時設置了 HTTP 與 HTTPS.

export HTTP_PROXY=http://your.proxy.name:8080
export HTTPS_PROXY=http://your.proxy.name:8080

如今你能夠重啓整個服務以及Docker容器:

docker@boot2docker:~$ sudo /etc/init.d/docker restart
docker@boot2docker:~$ exit
Connection to localhost closed.

接下來就能夠順利的運行鏡像了:

bash-3.2$ docker search ubuntu
NAME                                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                                           Official Ubuntu base image                      356                  
stackbrew/ubuntu                                 Official Ubuntu base image                      39                   
crashsystems/gitlab-docker                       A trusted, regularly updated build of GitL...

這個改變即便之後的虛擬機重啓重置也都一直會被保留,所以只須要被設置一次。

Docker Hub Mirror

DaoCloud提供Docker Hub Mirror服務。用戶能夠進入Docker Hub Mirror註冊入口註冊。在進入控制檯頁面後直接點擊 啓動你的加速器後,您便可獲得一個Mirror的地址,將該地址配置在Docker Daemon的啓動腳本中,重啓Docker Daemon便可使得Docker Hub Mirror配置生效。

  • Ubuntu

安裝或升級Docker

Docker 1.3.2版本以上才支持Docker Hub Mirror機制,若是您尚未安裝Docker或者版本太低,請安裝或升級版本。

配置Docker Hub Mirror

sudo echo "DOCKER_OPTS=\"$DOCKER_OPTS --registry-mirror=http://xxx.m.daocloud.io\"" >> /etc/default/docker service docker restart

請將xxx替換爲您在 DaoCloud 上註冊後,爲您專屬生成的Mirror地址連接名。 該腳本能夠將 --registry-mirror 加入到您的Docker配置文件 /etc/defaults/docker中。

盡情享受Docker Hub Mirror

Docker Hub Mirror使用不須要任何附件操做,就像這樣下載官方Ubuntu鏡像

docker pull ubuntu
  • CentOS

安裝或升級Docker

Docker 1.3.2版本以上才支持Docker Hub Mirror機制,若是您尚未安裝Docker或者版本太低,請安裝或升級版本。

配置Docker Hub Mirror

sudo sed -i 's|OPTIONS=|OPTIONS=--registry-mirror=http://xxx.m.daocloud.io |g' /etc/sysconfig/docker service docker restart

請將xxx替換爲您在 DaoCloud 上註冊後,爲您專屬生成的Mirror地址連接名。

該腳本能夠將 --registry-mirror 加入到您的Docker配置文件/etc/defaults/docker中。

盡情享受Docker Hub Mirror

Docker Hub Mirror使用不須要任何附件操做,就像這樣下載官方Ubuntu鏡像

docker pull ubuntu
  • MAC

安裝或升級MAC版本下的Boot2Docker

Docker 1.3.2版本以上才支持Docker Hub Mirror機制,若是您尚未安裝Docker或者版本太低,請安裝或升級版本。

配置Docker Hub Mirror

請確認你的Boot2Docker已經啓動,並執行

boot2docker ssh sudo su echo "EXTRA_ARGS=\"--registry-mirror=http://xxx.m.daocloud.io\"" >> /var/lib/boot2docker/profile && exit exit boot2docker restart

請將xxx替換爲您在 DaoCloud 上註冊後,爲您專屬生成的Mirror地址連接名。

盡情享受Docker Hub Mirror

Docker Hub Mirror使用不須要任何附件操做,就像這樣下載官方Ubuntu鏡像

docker pull ubuntu
  • Windows

安裝或升級MAC版本下的Boot2Docker

Docker 1.3.2版本以上才支持Docker Hub Mirror機制,若是您尚未安裝Docker或者版本太低,請安裝或升級版本。

配置Docker Hub Mirror

進入Boot2Docker Start Shell,並執行

sudo su echo "EXTRA_ARGS=\"--registry-mirror=http://xxx.m.daocloud.io\"" >> /var/lib/boot2docker/profile exit # 從新啓動Boot2Docker

請將xxx替換爲您在 DaoCloud 上註冊後,爲您專屬生成的Mirror地址連接名

盡情享受Docker Hub Mirror

Docker Hub Mirror使用不須要任何附件操做,就像這樣下載官方Ubuntu鏡像

docker pull ubuntu

Hello World

在Docker的學習中咱們依舊能夠借鑑經典的HelloWorld,直接運行docker run hello-world便可,不過須要注意的是,因爲總所周知的緣由,國內每每沒法順利的下載鏡像,若是遇到相似的網絡的錯誤能夠參考上文中的代理或者鏡像的設置。

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
511136ea3c5a: Pull complete
31cbccb51277: Pull complete
e45a5af57b00: Pull complete
hello-world:latest: The image you are pulling has been verified.
Important: image verification is a tech preview feature and should not be
relied on to provide security.
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.


To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
   (Assuming it was not already locally available.)
3. The Docker daemon created a new container from that image which runs the
   executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
   to your terminal.


To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash


For more examples and ideas, visit:
http://docs.docker.com/userguide/

Run Commands(運行命令)

你的Container會在你結束命令以後自動退出,使用如下的命令選項能夠將容器保持在激活狀態:

  • -i 即便在沒有附着的狀況下依然保持STDIN處於開啓。單純使用-i命令是不會出現root@689d580b6416:/ 這種前綴。

  • -t 分配一個僞TTY控制檯

因此run命令就變成了:

docker run -it -d shykes/pybuilder bin/bash

若是但願可以附着到一個已經存在的容器中,則利用exec命令:

docker exec -it CONTAINER_ID /bin/bash

Docker Commands

本章主要對於常見的Docker命令行命令進行詳細介紹。

LifeCycle

Containers

若是隻是但願有一個暫時性的容器,可使用 docker run --rm 將會在容器運行完畢以後刪除該容器。

若是但願在打開某個容器以後可以與其進行交互, docker run -t -i 會建立一個TTY控制檯。

若是但願可以移除全部與該容器相關的Volume,可使用-v參數: docker rm -v.

Images

Info

Containers

  • docker ps 會列舉出全部正在運行的容器

docker ps -a 會展現出全部正在運行的和已經中止的容器

Images

Import&Export

  • docker cp 在容器與本地文件系統之間進行文件複製

  • docker export 將某個容器中的文件系統的內容輸出到某個tar文件中

Executing Commands

若是須要在某個名字爲foo的容器中運行交互命令,可使用:

docker exec -it foo /bin/bash.

Fundamental

Containers

An instance of an image is called container

容器是Docker的核心概念,其相較於咱們認爲的虛擬機就比如進程中的線程同樣。

LifeCycle

A docker container exits when its main process finishes.

Images

Export/Import

Docker 背後的驅動力之一就是經過全部的 Docker 使服務器 能建立一個一致的環境,而且能建立一個能運行在任何 Docker 服務器上的合適的模板或是鏡像。所以,Docker 能很是完美的支持,能很是容易的導出一個正在運行的容器,而且從新導入另一臺 Docker 服務器。讓咱們假設一下,例如這個示例,你有一個你將移動到另一臺服務器去的正在運行的容器。這個進程的功能就是把這個容器保存爲一個鏡像,保存成 一個 tar 文件,把它移動到新的服務器,而且把這個鏡像加載進新的 docker 服務器。

  • 將Container提交爲鏡像

$ docker commit 3a09b2588478 mynewimage
4d2eab1c0b9a13c83abd72b38e5d4b4315de3c9967165f78a7b817ca99bf191e
  • 將鏡像打包

$ docker save mynewimage > /tmp/mynewimage.tar
  • 在新的機器上載入鏡像

$ docker load < /tmp/mynewimage.tar
  • 查看鏡像狀態

最後,運行 docker images 命令檢查鏡像如今是否可用。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
mynewimage          latest              4d2eab1c0b9a        5 minutes ago       278.1 MB
ubuntu              14.04               ad892dd21d60        11 days ago         275.5 MB
<none>              <none>              6b0a59aa7c48        11 days ago         169.4 MB
<none>              <none>              6cfa4d1f33fb        7 weeks ago         0 B

Dockerfile

Dockerfile最佳實踐

Dockerfile優化淺談

Dockerfile 由一行行命令語句組成,而且支持以 # 開頭的註釋行。通常的,Dockerfile 分爲四部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時執行指令。例如:

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..

# Base image to use, this must be set as the first line
FROM ubuntu

# Maintainer: docker_user <docker_user at email.com> (@docker_user)
MAINTAINER docker_user docker_user@email.com

# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# Commands when creating a new container
CMD /usr/sbin/nginx

其中,一開始必須指明所基於的鏡像名稱,接下來推薦說明維護者信息。後面則是鏡像操做指令,例如 RUN 指令,RUN 指令將對鏡像執行跟隨的命令。每運行一條 RUN 指令,鏡像添加新的一層,並提交。最後是 CMD 指令,來指定運行容器時的操做命令。

最後,這邊有一個Docker官方MongoDB的例子:

#
# MongoDB Dockerfile
#
# https://github.com/dockerfile/mongodb
#

# Pull base image.
FROM dockerfile/ubuntu

# Install MongoDB.
RUN \
  apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 && \
  echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' > /etc/apt/sources.list.d/mongodb.list && \
  apt-get update && \
  apt-get install -y mongodb-org && \
  rm -rf /var/lib/apt/lists/*

# Define mountable directories.
VOLUME ["/data/db"]

# Define working directory.
WORKDIR /data

# Define default command.
CMD ["mongod"]

# Expose ports.
#   - 27017: process
#   - 28017: http
EXPOSE 27017
EXPOSE 28017

指令

指令的通常格式爲 INSTRUCTION arguments,指令包括 FROMMAINTAINERRUN 等。

  • FROM

格式爲 FROM <image>FROM <image>:<tag>

第一條指令必須爲 FROM 指令。而且,若是在同一個Dockerfile中建立多個鏡像時,可使用多個 FROM 指令(每一個鏡像一次)。

  • MAINTAINER

格式爲 MAINTAINER <name>,指定維護者信息。

  • RUN

格式爲 RUN <command>RUN ["executable", "param1", "param2"]

前者將在 shell 終端中運行命令,即 /bin/sh -c;後者則使用 exec 執行。指定使用其它終端能夠經過第二種方式實現,例如 RUN ["/bin/bash", "-c", "echo hello"]

每條 RUN 指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可使用 \ 來換行。

  • CMD

支持三種格式

  • CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;

  • CMD command param1 param2/bin/sh 中執行,提供給須要交互的應用;

  • CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數;

指定啓動容器時執行的命令,每一個 Dockerfile 只能有一條 CMD 命令。若是指定了多條命令,只有最後一條會被執行。

若是用戶啓動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。

  • EXPOSE

格式爲 EXPOSE <port> [<port>...]

告訴 Docker 服務端容器暴露的端口號,供互聯繫統使用。在啓動容器時須要經過 -P,Docker 主機會自動分配一個端口轉發到指定的端口。

  • ENV

格式爲 ENV<key><value>。指定一個環境變量,會被後續 RUN 指令使用,並在容器運行時保持。

例如

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
  • ADD

格式爲 ADD<src><dest>

該命令將複製指定的 <src> 到容器中的 <dest>。其中 <src> 能夠是Dockerfile所在目錄的一個相對路徑;也能夠是一個 URL;還能夠是一個 tar 文件(自動解壓爲目錄)。

  • COPY

格式爲 COPY <src><dest>

複製本地主機的 <src>(爲 Dockerfile 所在目錄的相對路徑)到容器中的 dest

當使用本地目錄爲源目錄時,推薦使用 COPY

  • ENTRYPOINT

兩種格式:

  • ENTRYPOINT ["executable", "param1", "param2"]

  • ENTRYPOINT command param1 param2(shell中執行)。

配置容器啓動後執行的命令,而且不可被 docker run 提供的參數覆蓋。

每一個 Dockerfile 中只能有一個 ENTRYPOINT,當指定多個時,只有最後一個起效。

  • VOLUME

格式爲 VOLUME ["/data"]

建立一個能夠從本地主機或其餘容器掛載的掛載點,通常用來存放數據庫和須要保持的數據等。

  • USER

格式爲 USER daemon

指定運行容器時的用戶名或 UID,後續的 RUN 也會使用指定用戶。

當服務不須要管理員權限時,能夠經過該命令指定運行用戶。而且能夠在以前建立所須要的用戶,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要臨時獲取管理員權限可使用 gosu,而不推薦 sudo

  • WORKDIR

格式爲 WORKDIR /path/to/workdir

爲後續的 RUNCMDENTRYPOINT 指令配置工做目錄。

可使用多個 WORKDIR 指令,後續命令若是參數是相對路徑,則會基於以前命令指定的路徑。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

則最終路徑爲 /a/b/c

  • ONBUILD

格式爲 ONBUILD [INSTRUCTION]

配置當所建立的鏡像做爲其它新建立鏡像的基礎鏡像時,所執行的操做指令。

例如,Dockerfile 使用以下的內容建立了鏡像 image-A

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

若是基於 image-A 建立新的鏡像時,新的Dockerfile中使用 FROM image-A指定基礎鏡像時,會自動執行 ONBUILD 指令內容,等價於在後面添加了兩條指令。

FROM image-A

#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

使用 ONBUILD 指令的鏡像,推薦在標籤中註明,例如 ruby:1.9-onbuild

建立鏡像

編寫完成 Dockerfile 以後,能夠經過 docker build 命令來建立鏡像。

基本的格式爲 docker build [選項] 路徑,該命令將讀取指定路徑下(包括子目錄)的 Dockerfile,並將該路徑下全部內容發送給 Docker 服務端,由服務端來建立鏡像。所以通常建議放置 Dockerfile 的目錄爲空目錄。也能夠經過 .dockerignore 文件(每一行添加一條匹配模式)來讓 Docker 忽略路徑下的目錄和文件。

要指定鏡像的標籤信息,能夠經過 -t 選項,例如

$ sudo docker build -t myrepo/myapp /tmp/test1/

Storage:存儲

Volume

docker-indepth-volumes

深刻理解Docker Volume

數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,能夠提供不少有用的特性:

  • 數據卷能夠在容器之間共享和重用

  • 對數據卷的修改會立馬生效

  • 對數據卷的更新,不會影響鏡像

  • 卷會一直存在,直到沒有容器使用

*數據卷的使用,相似於 Linux 下對目錄或文件進行 mount。

建立與掛載

建立

在用 docker run 命令的時候,使用 -v 標記來建立一個數據卷並掛載到容器裏。在一次 run 中屢次使用能夠掛載多個數據卷。

下面建立一個 web 容器,並加載一個數據捲到容器的 /data 目錄。

$ sudo docker run -d -P --name web -v /data training/webapp python app.py

*注意:也能夠在 Dockerfile 中使用 VOLUME 來添加一個或者多個新的捲到由該鏡像建立的任意容器。這將在容器內建立路徑/data,它存在於聯合文件系統外部並能夠在主機上直接訪問。任何在該鏡像/data路徑的文件將被複制到volume。咱們可使用docker inspect命令找出Volume在主機存儲的地方:

$ docker inspect -f {{.Volumes}} web

你會看到如下相似內容:

map[/data:/var/lib/docker/vfs/dir/cde167197ccc3e138a14f1a4f...b32cec92e79059437a9]

這說明Docker把在/var/lib/docker下的某個目錄掛載到了容器內的/data目錄下。讓咱們從主機上添加文件到此文件夾下:

$ sudo touch /var/lib/docker/vfs/dir/cde167197ccc3e13814f...b32ce9059437a9/test-file

進入咱們的容器內能夠看到:

$ root@CONTAINER:/# ls /data test-file

改變會當即生效只要將主機的目錄掛載到容器的目錄上。咱們能夠在Dockerfile中經過使用VOLUME指令來達到相同的效果:

FROM debian:wheezy 
VOLUME /data

掛載目錄

使用 -v 標記也能夠指定掛載一個本地主機的目錄到容器中去。

$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

上面的命令加載主機的 /src/webapp 目錄到容器的 /opt/webapp目錄。這個功能在進行測試的時候十分方便,好比用戶能夠放置一些程序到本地目錄中,來查看容器是否正常工做。本地目錄的路徑必須是絕對路徑,若是目錄不存在 Docker 會自動爲你建立它。

*注意:Dockerfile 中不支持這種用法,這是由於 Dockerfile 是爲了移植和分享用的。然而,不一樣操做系統的路徑格式不同,因此目前還不能支持。

Docker 掛載數據卷的默認權限是讀寫,用戶也能夠經過 :ro 指定爲只讀。

$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:ro
training/webapp python app.py

加了 :ro 以後,就掛載爲只讀了。

掛載文件

-v 標記也能夠從主機掛載單個文件到容器中

$ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

這樣就能夠記錄在容器輸入過的命令了。

*注意:若是直接掛載一個文件,不少文件編輯工具,包括 vi 或者 sed --in-place,可能會形成文件 inode 的改變,從 Docker 1.1.0起,這會致使報錯誤信息。因此最簡單的辦法就直接掛載文件的父目錄。

Data Volume Container(數據卷容器)

數據共享

Separate Volume From 1.9

自從Docker 1.9版本以後,volume再也不僅僅做爲docker run的一個flag,也做爲一個單獨的子命令出如今Docker中。底層也爲volume添加了諸如ls、create、inspect和rm等volume子命令的api。新的volume子命令能夠容許用戶先建立volume,而後在啓動的container的時候進行掛載,此舉也更加方便了volume的管理。

$ docker volume create --name hello
hello
$ docker run -d -v hello:/world busybox ls /world

而在一個獨立的Volume被建立以後,就能夠經過inspect命令來進行信息查看:

Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...]

Inspect one or more volumes

  -f, --format=       Format the output using the given go template.
  --help=false        Print usage

該命令會返回某個數據卷的基本信息,大概樣式以下圖所示:

$ docker volume create
85bffb0677236974f93955d8ecc4df55ef5070117b0e53333cc1b443777be24d
$ docker volume inspect 85bffb0677236974f93955d8ecc4df55ef5070117b0e53333cc1b443777be24d
[
  {
      "Name": "85bffb0677236974f93955d8ecc4df55ef5070117b0e53333cc1b443777be24d",
      "Driver": "local",
      "Mountpoint": "/var/lib/docker/volumes/85bffb0677236974f93955d8ecc4df55ef5070117b0e53333cc1b443777be24d/_data"
  }
]

$ docker volume inspect --format '{{ .Mountpoint }}' 85bffb0677236974f93955d8ecc4df55ef5070117b0e53333cc1b443777be24d
/var/lib/docker/volumes/85bffb0677236974f93955d8ecc4df55ef5070117b0e53333cc1b443777be24d/_data

Data Transfer

copying-data-between-docker-containers

Network:網絡

Docker Networking: Reborn

Docker 1.9中正式引入了所謂的"Container Network Model",也就適合所謂的 CNM的概念。CNM即用於建立小型微分割的網絡來使得不一樣組的容器之間進行相互鏈接。

Basic Usage

端口映射

容器中能夠運行一些網絡應用,要讓外部也能夠訪問這些應用,能夠經過 -P-p 參數來指定端口映射。

當使用 -P 標記時,Docker 會隨機映射一個 49000~49900 的端口到內部容器開放的網絡端口。

使用 docker ps 能夠看到,本地主機的 49155 被映射到了容器的 5000 端口。此時訪問本機的 49155 端口便可訪問容器內 web 應用提供的界面。

$ sudo docker run -d -P training/webapp python app.py
$ sudo docker ps -l
CONTAINER ID  IMAGE                   COMMAND       CREATED        STATUS        PORTS                    NAMES
bc533791f3f5  training/webapp:latest  python app.py 5 seconds ago  Up 2 seconds  0.0.0.0:49155->5000/tcp  nostalgic_morse

一樣的,能夠經過 docker logs 命令來查看應用的信息。

$ sudo docker logs -f nostalgic_morse
* Running on http://0.0.0.0:5000/
10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 -
10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -

-p(小寫的)則能夠指定要映射的端口,而且,在一個指定端口上只能夠綁定一個容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort

  • 映射全部接口地址

使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,能夠執行

$ sudo docker run -d -p 5000:5000 training/webapp python app.py

此時默認會綁定本地全部接口上的全部地址。

  • 映射到指定地址的指定端口

可使用 ip:hostPort:containerPort 格式指定映射使用一個特定地址,好比 localhost 地址 127.0.0.1

$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
  • 映射到指定地址的任意端口

使用 ip::containerPort 綁定 localhost 的任意端口到容器的 5000 端口,本地主機會自動分配一個端口。

$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py

還可使用 udp 標記來指定 udp 端口

$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
  • 查看映射端口配置

使用 docker port 來查看當前映射的端口配置,也能夠查看到綁定的地址

$ docker port nostalgic_morse 5000
127.0.0.1:49155.

注意:

  • 容器有本身的內部網絡和 ip 地址(使用 docker inspect 能夠獲取全部的變量,Docker 還能夠有一個可變的網絡配置。)

  • -p 標記能夠屢次使用來綁定多個端口

例如

$ sudo docker run -d -p 5000:5000  -p 3000:80 training/webapp python app.py

注意,網絡映射的操做只會在run命令中起做用,若是已經運行了一個容器,須要從新設置其網絡映射狀況,請使用commit將容器轉化爲鏡像以後再建立新的容器。

容器互聯(Links)

容器的鏈接(linking)系統是除了端口映射外,另外一種跟容器中應用交互的方式。

該系統會在源和接收容器之間建立一個隧道,接收容器能夠看到源容器指定的信息。

自定義容器命名

鏈接系統依據容器的名稱來執行。所以,首先須要自定義一個好記的容器命名。

雖然當建立容器的時候,系統默認會分配一個名字。自定義命名容器有2個好處:

  • 自定義的命名,比較好記,好比一個web應用容器咱們能夠給它起名叫web

  • 當要鏈接其餘容器時候,能夠做爲一個有用的參考點,好比鏈接web容器到db容器

使用 --name 標記能夠爲容器自定義命名。

$ sudo docker run -d -P --name web training/webapp python app.py

使用 docker ps 來驗證設定的命名。

$ sudo docker ps -l
CONTAINER ID  IMAGE                  COMMAND        CREATED       STATUS       PORTS                    NAMES
aed84ee21bde  training/webapp:latest python app.py  12 hours ago  Up 2 seconds 0.0.0.0:49154->5000/tcp  web

也可使用 docker inspect 來查看容器的名字

$ sudo docker inspect -f "{{ .Name }}" aed84ee21bde
/web

注意:容器的名稱是惟一的。若是已經命名了一個叫 web 的容器,當你要再次使用 web 這個名稱的時候,須要先用docker rm 來刪除以前建立的同名容器。

在執行 docker run 的時候若是添加 --rm 標記,則容器在終止後會馬上刪除。注意,--rm-d 參數不能同時使用。

容器互聯

使用 --link 參數可讓容器之間安全的進行交互。

下面先建立一個新的數據庫容器。

$ sudo docker run -d --name db training/postgres

刪除以前建立的 web 容器

$ docker rm -f web

而後建立一個新的 web 容器,並將它鏈接到 db 容器

$ sudo docker run -d -P --name web --link db:db training/webapp python app.py

此時,db 容器和 web 容器創建互聯關係。

--link 參數的格式爲 --link name:alias,其中 name 是要連接的容器的名稱,alias 是這個鏈接的別名。

使用 docker ps 來查看容器的鏈接

$ docker ps
CONTAINER ID  IMAGE                     COMMAND               CREATED             STATUS             PORTS                    NAMES
349169744e49  training/postgres:latest  su postgres -c '/usr  About a minute ago  Up About a minute  5432/tcp                 db, web/db
aed84ee21bde  training/webapp:latest    python app.py         16 hours ago        Up 2 minutes       0.0.0.0:49154->5000/tcp  web

能夠看到自定義命名的容器,db 和 web,db 容器的 names 列有 db 也有 web/db。這表示 web 容器連接到 db 容器,web 容器將被容許訪問 db 容器的信息。

Docker 在兩個互聯的容器之間建立了一個安全隧道,並且不用映射它們的端口到宿主主機上。在啓動 db 容器的時候並無使用 -p-P 標記,從而避免了暴露數據庫端口到外部網絡上。

Docker 經過 2 種方式爲容器公開鏈接信息:

  • 環境變量

  • 更新 /etc/hosts 文件

使用 env 命令來查看 web 容器的環境變量

$ sudo docker run --rm --name web2 --link db:db training/webapp env
. . .
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5000_TCP=tcp://172.17.0.5:5432
DB_PORT_5000_TCP_PROTO=tcp
DB_PORT_5000_TCP_PORT=5432
DB_PORT_5000_TCP_ADDR=172.17.0.5
. . .

其中 DB_ 開頭的環境變量是供 web 容器鏈接 db 容器使用,前綴採用大寫的鏈接別名。

除了環境變量,Docker 還添加 host 信息到父容器的 /etc/hosts 的文件。下面是父容器 web 的 hosts 文件

$ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7  aed84ee21bde
. . .
172.17.0.5  db

這裏有 2 個 hosts,第一個是 web 容器,web 容器用 id 做爲他的主機名,第二個是 db 容器的 ip 和主機名。能夠在 web 容器中安裝 ping 命令來測試跟db容器的連通。

root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping db
PING db (172.17.0.5): 48 data bytes
56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms
56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms
56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms

用 ping 來測試db容器,它會解析成 172.17.0.5。*注意:官方的 ubuntu 鏡像默認沒有安裝 ping,須要自行安裝。

用戶能夠連接多個父容器到子容器,好比能夠連接多個 web 到 db 容器上。

Networking(網絡)

在Docker 1.9以後,Docker正式宣佈能夠將Networking應用於生產環境中,而且能夠與Swarm以及Compose進行較好的結合。與傳統的Links相比,Networking具備如下優點:

  • 容許不一樣物理主機或者虛擬主機上的容器進行通訊

  • 使用了Networking的容器能夠很方便地進行中止、啓動或者重啓等操做而不用擔憂會影響到與其餘容器之間的鏈接

  • 並不須要在鏈接到某個容器以前就直接建立它,換言之,Networking再也不像本來的Links同樣會依賴某個容器而存在

Single Host Networking

能夠直接使用docker network命令來使用Networking,其中可使用docker network create來建立一個新的網絡,在這個示例中,咱們會建立一個叫作frontend的網絡而且在其中運行一個nginx容器:

$ docker network create frontend
$ docker run -itd --net=frontend --name web nginx

咱們使用網絡來分割應用,乃至於分割應用中的不一樣模塊。在本例子中,咱們能夠建立另外一個包含了應用程序的網絡app,而後將這個網絡與frontend網絡相連,命令以下所示:

$ docker network create app
$ docker run -itd --name myapp --net=app <my application container>
$ docker network connect app web

這樣咱們的Nginx服務器就可使用myapp.app這個主機名來鏈接到應用程序中。咱們建立兩個基於busybox的容器來進行嘗試:

$ docker run -d --name rose --net=frontend busybox top
c1fa2dc7fa3a412b52b53f5facd25ba11e99c362d77be8cea4ff49f3d5e2cafc

$ docker run --rm --net=frontend busybox ping -c 4 rose
PING rose (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.122 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.078 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.098 ms
64 bytes from 172.19.0.2: seq=3 ttl=64 time=0.241 ms

咱們已將第二個容器附着到frontend網路中,而且用ping命令來進行內建的容器發現,咱們能夠用inspect命令來查看網絡的詳情:

$ docker network inspect frontend
[
    {
        "Name": "frontend",
        "Id": "a639a457122020faa69a4ab906bc33217c9c6d73048f3dbbb69e53dbe5e0952c",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {
            "c1fa2dc7fa3a412b52b53f5facd25ba11e99c362d77be8cea4ff49f3d5e2cafc": {
                "EndpointID": "976bab21d4a11cd21d5d1c1560f67f39ef15245662aeacf097eb1d5c148ed748",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]

在前端網絡以外,咱們也能夠建立一個自定義的後端網絡,用於鏈接其餘容器:

$ docker network create backend
09733cac7890edca439cdc3d476b4cd1959e44065217aa581d359575b8d2288f
$ docker network connect backend rose
$ docker network inspect backend

    {
        "name": "backend",
        "id": "09733cac7890edca439cdc3d476b4cd1959e44065217aa581d359575b8d2288f",
        "scope": "local",
        "driver": "bridge",
        "ipam": {
            "driver": "default",
            "config": [
                {}
            ]
        },
        "containers": {
            "c1fa2dc7fa3a412b52b53f5facd25ba11e99c362d77be8cea4ff49f3d5e2cafc": {
                "endpoint": "438730c588915dd54dc694efdb3a15c77bc5e86c744f5f87a65f6ac46b43e5ad",
                "mac_address": "02:42:ac:14:00:02",
                "ipv4_address": "172.20.0.2/16",
                "ipv6_address": ""
            }
        },
        "options": {}
    }
]

再看一下容器中具體的網絡的設置:

$ docker inspect -f '{{ json .NetworkSettings }}' rose
{
  "Bridge": "",
  "SandboxID": "b600bebe1e2bb6dee92335e6acfe49215c30c4964d7a982711ec12c6acca3309",
  "HairpinMode": false,
  "LinkLocalIPv6Address": "",
  "LinkLocalIPv6PrefixLen": 0,
  "Ports": {},
  "SandboxKey": "/var/run/docker/netns/b600bebe1e2b",
  "SecondaryIPAddresses": null,
  "SecondaryIPv6Addresses": null,
  "EndpointID": "",
  "Gateway": "",
  "GlobalIPv6Address": "",
  "GlobalIPv6PrefixLen": 0,
  "IPAddress": "",
  "IPPrefixLen": 0,
  "IPv6Gateway": "",
  "MacAddress": "",
  "Networks": {
    "backend": {
      "EndpointID": "438730c588915dd54dc694efdb3a15c77bc5e86c744f5f87a65f6ac46b43e5ad",
      "Gateway": "172.20.0.1",
      "IPAddress": "172.20.0.2",
      "IPPrefixLen": 16,
      "IPv6Gateway": "",
      "GlobalIPv6Address": "",
      "GlobalIPv6PrefixLen": 0,
      "MacAddress": "02:42:ac:14:00:02"
    },
    "frontend": {
      "EndpointID": "976bab21d4a11cd21d5d1c1560f67f39ef15245662aeacf097eb1d5c148ed748",
      "Gateway": "172.19.0.1",
      "IPAddress": "172.19.0.2",
      "IPPrefixLen": 16,
      "IPv6Gateway": "",
      "GlobalIPv6Address": "",
      "GlobalIPv6PrefixLen": 0,
      "MacAddress": "02:42:ac:13:00:02"
    }
  }
}

而在容器中使用ifconfig命令查看時:

$ docker exec rose ifconifg
eth0      Link encap:Ethernet  HWaddr 02:42:AC:13:00:02
          inet addr:172.19.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2238 (2.1 KiB)  TX bytes:1208 (1.1 KiB)

eth1      Link encap:Ethernet  HWaddr 02:42:AC:14:00:02
          inet addr:172.20.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1296 (1.2 KiB)  TX bytes:648 (648.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

而若是要將某個容器從網絡中斷開時,可使用以下命令:

$ docker network disconnect backend rose

這種網絡配置方式的初衷即將服務獨立出來成爲一個網絡中不一樣的容器之間相互交流的惟一信息。換言之,在實踐中,須要構建出大量的小型網絡,每一個網絡中只負責某個服務的通訊,而且不一樣的網絡之間應該是相互隔離的。一個典型的例子就是負載均衡器、前端、後端以及一個數據庫。

Network Customization

在建立網絡的時候咱們也能夠設置不少的自定義的配置:

--aux-address=map[]      auxiliary ipv4 or ipv6 addresses used by Network driver
  -d, --driver="bridge"    Driver to manage the Network
  --gateway=[]             ipv4 or ipv6 Gateway for the master subnet
  --help=false             Print usage
  --ip-range=[]            allocate container ip from a sub-range
  --ipam-driver=default    IP Address Management Driver
  -o, --opt=map[]          set driver specific options
  --subnet=[]              subnet in CIDR format that represents a network segment

咱們首先來看下--driver選項,該選項能夠來選定具體的網絡驅動方式來管理網絡,目前Docker提供了以下兩種驅動器:

  • bridge -- This driver provides the same sort of networking via veth bridge devices that prior versions of docker use, it is the default.

  • overlay -- Not to be confused with the "overlay" storage driver (thanks overlayfs), this driver provides native multi-host networking for docker clusters. When using swarm, this is the default driver.

另外一個經常使用的選項是--ipam-driver,用來肯定IP地址是如何分配的。目前Docker僅內置了一種IP地址分配方案,將來會添加上DHCP IAMP方式。

Multi-Host Networking

Manager

Web Interface

DockerUI

相關文章
相關標籤/搜索