概念
- Registry A service responsible for hosting and distributing images.
The default registry is the Docker Hub.
- Repository A collection of related images (usually providing
different versions of the same application or service).
- 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>
- amouat/revealjs 表示amouat用户的revealjs镜像。
- ubuntu 没有前缀表示该镜像属于“root”名字空间,由Docker
Inc管理,用于官方的通用镜像。
- 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>
- empty
volume挂载到容器中已经有文件的目录下时,该目录下的文件会被拷贝到volume。
- 非空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
端口映射的四种格式:
- \<containerPort\> This form binds the container port to a dynamic
port on all of the host’s interfaces:
example
docker run -p 3333 ...
- \<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 ...
- \<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 ...
- \<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
- Use joined containers when you want to use a single loopback
interface for communication between programs in different
containers.
- 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.
- 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,会有三个效果:
- Environment variables describing the target container’s end point
will be created.
- The link alias will be added to the DNS override list of the new
container with the IP address of the target container.
- 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
<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