个人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

相关文章
相关标签/搜索