概念

  1. Registry A service responsible for hosting and distributing images.

The default registry is the Docker Hub.

  1. Repository A collection of related images (usually providing

different versions of the same application or service).

  1. Tag An alphanumeric identifier attached to images within a

repository (e.g., 14.04 or stable ).

下面的命令会从Docker Hub Registry的amouat/revealjs
Repository中下载tag为latest的image。

`` example
docker pull amouat/revealjs:latest


| Term | Meaning |
|------------|------------------------------------------------------------------------------------------------|
| Image | A read-only layer |
| Name | The name of your image |
| Tag | As a verb, it refers to giving an image a name. As a noun, it's a modifier for your image name |
| Repository | A hosted collection of tagged images that together create the filesystem for a container |

<h2 id="Union File System">Union File System</h2>

UFS有时也称为union mount.
可将多种不同文件系统混合使用,让用户看起来像是同一个文件系统。 Docker
image由多个层组成。每个层就是一个只读文件系统。Dockerfile中每条指令都会添加新的一个层。当最终image被转换成container时(用docker
run或docker
create命令),Docker引擎会在image之上加一层可读可写的文件系统,这最后一层会做各种设置工作,如设置IP,主机名,ID,资源限制等。
AUFS限制最多能有127层,因此很多Dockerfile中会尽量把多个命令放在同一个RUN中执行,以减少image的层数。
Container的状态有以下几种:created, restarting, running, paused, or
exited.

<h1 id="Image">Image</h1>

<h2 id="Image Namespace">Image Namespace</h2>

  1. amouat/revealjs 表示amouat用户的revealjs镜像。
  2. ubuntu 没有前缀表示该镜像属于“root”名字空间,由Docker

Inc管理,用于官方的通用镜像。

  1. localhost:5000/wordpress 用主机或IP前缀,表示第三方Registry的image。

<h2 id="Build Image">Build Image</h2>

docker build命令需要两样东西:Dockerfile和build context。Build
context就是一系列本地文件和目录,这些文件和目录在Dockerfile中可以用ADD和COPY命令来引用。

example

docker build -t test/cowsay-dockerfile .


上面的命令中,'.'代表的当前目录即为build
context,当前目录下所有的文件和目录都会在构建时被传给docker
daemon。因此,一般来说,不能将包含很多文件的目录作为build context。

<h2 id="Image Layers">Image Layers</h2>

每个Image都是建立在另一Image之上,两个不同Image可以使用相同的parent
Image,因此,不同Image可以包含相同的Layer。在网络上分发Image就会比较方便,因为,已有的Layer不必再次传输。
Layer还可以节省存储空间。Layer只会被保存一次。由同一Layer衍生出两个不同的Image,在此Image之上的Container看到的就是相同的文件。不过,两个Container看不到对方对文件的修改。因为container
image
layer是只读的,container运行时,会新建一层可写的Layer,改动过的文件会在这一新层上建立备份。

<h1 id="Volume">Volume</h1>

<h2 id="两种类型">两种类型</h2>

Docker的Volume共有两种类型:一是bind mount,二是managed volume。

example

docker run --name bmweb_ro --volume ~/example-docs:/usr/local/apache2/htdocs/:ro -p 80:80 httpd:latest


bind mount由用户自行指定host文件目录与container文件目录的映射。

example

docker run -d -v /var/lib/cassandra/data --name cass-shared alpine echo Data Container


managed
volume中,-v参数指定的container的文件系统会对应到/var/lib/docker/vfs/dir/\<some
volume ID\>,该目录由docker服务进程管理。

example

docker inspect -f "{{json .Volumes}}" cass-shared
{"/var/lib/cassandra/data":"/mnt/sda1/var/lib/docker/vfs/dir/632fa59c..."}


<h2 id="共享Volume">共享Volume</h2>

Host-dependent sharing:

bash

mkdir ~/web-logs-example
docker run --name plath -d -v ~/web-logs-example:/data dockerinaction/ch4_writer_a
docker run --rm -v ~/web-logs-example:/reader-data alpine:latest head /reader-data/logA
cat ~/web-logs-example/logA
docker stop plath


使用volumes-from

bash

docker run --name fowler \
-v ~/example-books:/library/PoEAA \
-v /library/DSL \
alpine:latest \
echo "Fowler collection created."
docker run --name knuth \
-v /library/TAoCP.vol1 \
-v /library/TAoCP.vol2 \
-v /library/TAoCP.vol3 \
-v /library/TAoCP.vol4.a \
alpine:latest \
echo "Knuth collection created"
docker run --name reader \
--volumes-from fowler \
--volumes-from knuth \
alpine:latest ls -l /library/
List all volumes as they were
copied into new container
docker inspect --format "{{json .Volumes}}" reader


<h2 id="Data-packed volume container">Data-packed volume container</h2>

该模式中,数据是通过image来传播的。可让多个container共享某个image中的数据。在创建container时,将image中的数据拷贝到挂载的volume上,其它container就能读取到数据。

bash

docker run --name dpvc \
-v /config \
dockerinaction/ch4_packed /bin/sh -c 'cp /packed/* /config/'
docker run --rm --volumes-from dpvc \
alpine:latest ls /config
docker run --rm --volumes-from dpvc \
alpine:latest cat /config/packedData
docker rm -v dpvc


现在,出现了操作上的问题,为了检测这个问题,需要用到某个image上的工具,而这个image在工作开始时并未导入过。

bash

#Create data-packed volume container with tools
docker run --name tools dockerinaction/ch4_tools
#List shared tools
docker run --rm \
--volumes-from tools \
alpine:latest \
ls /operations/*
#Start another container with shared tools
docker run -d --name important_application \
--volumes-from tools \
dockerinaction/ch4_ia
#Use shared tool in running container
docker exec important_application /operations/tools/someTool
docker rm -vf important_application
docker rm -v tools


<h2 id="Polymorphic container pattern">Polymorphic container pattern</h2>

通过在volume中注入不同的数据,可改变container的行为,从而实现多态。一个多态的container就是可以通过替换volume而提供不同的功能的container。

bash

docker run --name devConfig \
-v /config \
dockerinaction/ch4_packed_config:latest \
/bin/sh -c 'cp /development/* /config/'
docker run --name prodConfig \
-v /config \
dockerinaction/ch4_packed_config:latest \
/bin/sh -c 'cp /production/* /config/'
docker run --name devApp \
--volumes-from devConfig \
dockerinaction/ch4_polyapp
docker run --name prodApp \
--volumes-from prodConfig \
dockerinaction/ch4_polyapp


<h2 id="Data Volume">Data Volume</h2>

Data
volume用来在容器文件系统之外存储数据的,以方便多个容器共享数据。(这意味着用commit来保存容器镜像时,data
volume中的内容不会被保存到相应的image中)。
除非在删除container之时使用docker rm -v,连带着删除data
volume,否则,就有可能造成dangling volume。dangling
volume没有被任何container引用,这样的volume可以用docker volume
prune来删除。

<h2 id="挂载时的注意点">挂载时的注意点</h2>

  1. empty

volume挂载到容器中已经有文件的目录下时,该目录下的文件会被拷贝到volume。

  1. 非空volume挂载到容器目录下时,容器原来目录下的文件会被盖掉。

<h1 id="Network">Network</h1>

<h2 id="Four network container archetypes">Four network container archetypes</h2>

docker network

archetypes Closed
Container除了loopback接口外,无法与外部网络通信:

example

docker run --rm --net none alpine:latest ip addr


用于生成随机数的应用可以考虑用Closed Container.

<h3 id="Bridged containers">Bridged containers</h3>

Bridge为默认的网络配置模式。

example

docker run --rm --net bridge alpine:latest ip addr


设置主机名:

example

docker run --rm --hostname barker alpine:latest nslookup barker


设置DNS:

example

docker run --rm --dns 8.8.8.8 alpine:latest nslookup docker.com


设置DNS search domain:

example

docker run --rm --dns-search docker.com busybox:latest nslookup registry.hub


自定义主机名:

example

docker run --rm --hostname mycontainer --add-host docker.com:127.0.0.1 --add-host test:10.10.10.2 alpine:latest cat /etc/hosts


端口映射的四种格式:

  1. \<containerPort\> This form binds the container port to a dynamic

port on all of the host’s interfaces:

example

docker run -p 3333 ...


  1. \<hostPort\>:\<containerPort\> This form binds the specified

container port to the specified port on each of the host’s
interfaces:

example

docker run -p 3333:3333 ...


  1. \<ip\>::\<containerPort\> This form binds the container port to a

dynamic port on the interface with the specified IP address:

example

docker run -p 192.168.0.32::2222 ...


  1. \<ip\>:\<hostPort\>:\<containerPort\> This form binds the container

port to the specified port on the interface with the specified IP
address:

example

docker run -p 192.168.0.32:1111:1111 ...


指定container需要公开的端口:

example

docker run -d --name philbin --expose 8000 -P dockerinaction/ch5_expose


-P选项会暴露container所有的已知端口。 查看container所有的端口映射:

example

docker port philbin


关闭inter-container communication:

example

docker -d --icc=false ...


定义bridge的子网:

example

docker -d --bip "192.168.0.128" ...


a classless inter-domain routing (CIDR) formatted address

example

docker -d --fixed-cidr "192.168.0.192/26"


设置mtu:

example

docker -d –mtu 1200


<h3 id="Joined Container">Joined Container</h3>

Joined Container会共享网络接口。

bash

docker run -d --name brady \
--net none alpine:latest \
nc -l 127.0.0.1:3333
docker run -it \
--net container:brady \
alpine:latest netstat –al


The best reasons to use joined containers

  1. Use joined containers when you want to use a single loopback

interface for communication between programs in different
containers.

  1. Use joined containers if a program in one container is going to

change the joined network stack and another program is going to use
that modified network.

  1. Use joined containers when you need to monitor the network traffic

for a program in another container.

<h3 id="Open Container">Open Container</h3>

没有network jail,container获得主机的全部网络接口。

example

docker run --rm --net host alpine:latest ip addr


<h3 id="link">link</h3>

连接是单向的、静态的、不可传递的。
新的container上创建link,会有三个效果:

  1. Environment variables describing the target container’s end point

will be created.

  1. The link alias will be added to the DNS override list of the new

container with the IP address of the target container.

  1. Most interestingly, if inter-container communication is disabled,

Docker will add specific firewall rules to allow communication
between linked containers.

bash

#Named target of a link
docker run -d --name importantData \
--expose 3306 \
dockerinaction/mysql_noauth \
service mysql_noauth start
#Create link and set alias to db
docker run -d --name importantWebapp \
--link imporantData:db \
dockerinaction/ch5_web startapp.sh -db tcp://db:3306


link是单向的网络依赖,连接的别名即为目标container主机名,别名需要在docker环境中保持唯一。如果某个container需要依赖特定别名的连接,(比如数据库的连接),那么最好先检查这一点。
比如某应用依赖tcp://database:3306,这就必须保证运行mysql的container的别名为database。
连接的信息多会以环境变量的形式传递给container。

example _PORT___PORT _PORT___ADDR _PORT___PROTO _PORT__

<h1 id="Dockfile">Dockfile</h1>

<h2 id="示例">示例</h2>

bash

FROM debian
MAINTAINER John Smith
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]


<h2 id="ADD">ADD</h2>

example

ADD my.tar.gz /opt/libeatmydata/


使用ADD添加文件时,只有本地的tar.gz文件会被自动解压。下面的代码只会添加tar.gz文件:

example

ADD https://www.flamingspork.com/projects/libeatmydata/libeatmydata-105.tar.gz /opt/libeatmydata/


<h1 id="Cookbook">Cookbook</h1>

  • Using alternative registries full repository specification
example

[REGISTRYHOST/][USERNAME/]NAME[:TAG]
docker pull quay.io/dockerinaction/ch3_hello_registry:latest


删除镜像:

example

docker rmi quay.io/dockerinaction/ch3_hello_registry


  • Images as files
example

docker pull busybox:latest
docker save -o myfile.tar busybox:latest
docker load –i myfile.tar

``