Simple Docker: Basics

简介

Docker是一个基于LXC技术之上构建的Container容器引擎。源代码托管与Github,基于Go语言编写并遵从Apache2.0协议。
Docker在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。

Docker要解决的问题

  • 复杂的环境管理,简化部署多种应用实例
  • 云计算时代的到来,提供新的软件配置和管理方法
  • 虚拟化手段的变化,更加轻量级的LXC,更加灵活和快速
  • LXC的便携性,易于分发和标准化管理方法的创新

Why Docker

  • 更快速的交付和部署,开发者使用一个标准的镜像来构建一套开发容器,开发完成后运维人员直接可以使用这个容器部署。
  • 更高效的虚拟化,Docker 容器的运行不需要额外的 hypervisor(虚拟机监视器) 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。
  • 更轻松的迁移和扩展,Docker容器几乎可以在任意平台上运行。
  • 更简单的管理,所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。

镜像

Docker就是一个只读的模板。例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序。
镜像用来创建Docker容器。
镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

容器

容器是独立运行的一个或一组应用,以及它们的运行态环境。
Docker 利用容器来运行应用。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

仓库

仓库是集中存放镜像文件的场所。仓库经常与仓库注册服务器混为一谈,不做区分。
仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

核心技术

  • Docker的核心是一个操作系统级虚拟化的方法:
  • 隔离性(Linux Namespace(ns)):每个实例之间互不影响,相互隔离。一般硬件虚拟化方法给的方案是VM,LXC给出的方法是container,更细一点讲是kernel namespace。其中,pid、net、ipc、mnt、uts、user等namespace将contanier的进程、网络、消息、文件系统、UTS和用户空间隔开。
  • 可配额/可度量(Control Groups):cgroups实现了对资源的配额和度量。cgroups使用简单,提供类似文件的接口,在/cgroup下创建一个文件夹即可新建一个group,在此文件夹中新建task文件,并将pid写入该文件,即可实现对该进程的资源控制。
  • 便携性(AUFS):AUFS(Another)是一种Union FS,简单来说就是支持将不同目录挂载到同一虚拟文件系统下的文件系统。
  • 安全性

配置Docker

CentOs6.5 上提供的Docker包名为 dicker-io:
    $ sudo yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm
    $ sudo yum install docker-io
按照官方文档进行操作:
启动Docker:
    $ sudo service docker start
设置Docker随系统启动:
    $ sudo chkconfig docker on
获取一个Ubuntu 12.04操作系统镜像:
    $ sudo docker pull ubuntu:12.04
列出已有的镜像:
    $ sudo docker images
Next we'll make sure that we can see the image by running:
    $ sudo docker images centos
This should generate some output similar to:
    $ sudo docker images centos
    REPOSITORY      TAG             IMAGE ID          CREATED             VIRTUAL SIZE
    centos          latest          0b443ba03958      2 hours ago         297.6 MB
Run a simple bash shell to test the image:
    $ sudo docker run -i -t centos /bin/bash
If everything is working properly, you'll get a simple bash prompt. Type exit to continue.

使用Dockerfile创建镜像

mkdir testdocker
cd testdocker
touch Dockerfile
Docker中每一行命令都创建镜像的一层:
# This is a comment                             # 注释
FROM ubuntu:14.04                               # FROM 指令告诉Docker使用哪个镜像作为基础
MAINTAINER Docker Newbee <newbee@docker.com>    # 开发者信息
RUN apt-get -qq update                          # RUN 开头的命令会在创建中运行,比如安装应用
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra

编写完成后:
sudo docker build -t="ouruser/sinatra:v2" .
其中 -t 标记来添加 tag,指定新的镜像的用户信息。 “.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径。

利用 ADD 命令复制本地文件到镜像;
用 EXPOSE 命令来向外部开放端口;
用 CMD 命令来描述容器启动后运行的程序等。例如

# put my local web site in myApp folder to /var/www
ADD myApp /var/www
# expose httpd port
EXPOSE 80
# the command to run
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]

启动镜像:
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash

使用docker tag 命令修改镜像标签:
$ sudo docker tag 5db5f8471261 ouruser/sinatra:devel  # 修改标签为devel
使用docker save 命令保存镜像到本地文件:
$ sudo docker save -o ubuntu_14.04.tar ubuntu:14.04
使用docker load 将导出的本地文件导入到本地镜像库:
$ sudo docker load --input ubuntu_14.04.tar
或
$ sudo docker load < ubuntu_14.04.tar
使用docker rmi 命令移除镜像:
$ sudo docker rmi training/sinatra

启动容器

新建并启动:
    $ sudo docker run ubuntu:12.04 /bin/echo 'Hello world'
    # 启动ubuntu:12.04容器输出'Hello world'并关闭
启动一个 bash 终端,允许用户进行交互:
    $ sudo docker run -t -i ubuntu:12.04 /bin/bash
    # 其中,-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止

使用 docker start 命令直接启动关闭状态的容器。
使用 docker ps 查看容器信息。
使用 docker logs 查看容器输出信息。
使用 docker stop 命令终止容器。
使用 docker restart 命令终止并重新启动容器。

命令行

docker version                      查看docker的版本号,包括客户端、服务端、依赖的Go等
docker info                         查看系统(docker)层面信息,包括管理的images, containers数等
docker search                       在docker index中搜索image
docker pull                         从docker registry server 中下拉image
docker push                         推送一个image或repository到registry
docker push :TAG                    同上,指定tag
docker inspect                      查看imagecontainer的底层信息
docker images                       TODO filter out the intermediate image layers (intermediate image layers 是什么)
docker images -a                    列出所有的images
docker ps                           默认显示正在运行中的container
docker ps -l                        显示最后一次创建的container,包括未运行的
docker ps -a                        显示所有的container,包括未运行的
docker logs                         查看container的日志,也就是执行命令的一些输出
docker rm                           删除一个或多个container
docker rm `docker ps -a -q`         删除所有的container
docker ps -a -q | xargs docker rm   同上, 删除所有的container
docker rmi                          删除一个或多个image
docker start/stop/restart           开启/停止/重启container
docker start -i                     启动一个container并进入交互模式
docker attach                       attach一个运行中的container
docker run                          使用image创建container并执行相应命令,然后停止
docker run -i -t  /bin/bash         使用image创建container并进入交互模式, login shell是/bin/bash
docker run -i -t -p                 将container的端口映射到宿主机的端口
docker commit  [repo:tag]           将一个container固化为一个新的image,后面的repo:tag可选
docker build                        寻找path路径下名为的Dockerfile的配置文件,使用此配置生成新的image
docker build -t repo[:tag]          同上,可以指定repo和可选的tag
docker build -                      使用指定的dockerfile配置文件,docker以stdin方式获取内容,使用此配置生成新的image
docker port                         查看本地哪个端口映射到container的指定端口,其实用docker ps 也可以看到

命令行参数

--api-enable-cors=false             开放远程API调用的 CORS 头信息。这个接口开关对想进行二次开发的上层应用提供了支持。
-b, --bridge=""                     挂载已经存在的网桥设备到 Docker 容器里。注意,使用 none 可以停用容器里的网络。
--bip=""                            使用 CIDR 地址来设定网络桥的 IP。注意,此参数和 -b 不能一起使用。
-D, --debug=false                   开启Debug模式。例如:docker -d -D
-d, --daemon=false                  开启Daemon模式
--dns=[]                            强制容器使用DNS服务器。例如: docker -d --dns 8.8.8.8
--dns-search=[]                     强制容器使用指定的DNS搜索域名。例如: docker -d --dns-search example.com
-e, --exec-driver="native"          强制容器使用指定的运行时驱动。例如:docker -d -e lxc
-G, --group="docker"                在后台运行模式下,赋予指定的Group到相应的unix socket上。注意,当此参数 --group 赋予空字符串时,将去除组信息。
-g, --graph="/var/lib/docker"       配置Docker运行时根目录
-H, --host=[]                       在后台模式下指定socket绑定,可以绑定一个或多个 tcp://host:port, unix:///path/to/socket, fd://* 或 fd://socketfd。
                                    $ docker -H tcp://0.0.0.0:2375 ps 或者
                                    $ export DOCKER_HOST="tcp://0.0.0.0:2375"
                                    $ docker ps
--icc=true                          启用内联容器的通信。
--ip="0.0.0.0"                      容器绑定IP时使用的默认IP地址
--ip-forward=true                   启动容器的 net.ipv4.ip_forward
--iptables=true                     启动Docker容器自定义的iptable规则
--mtu=0                             设置容器网络的MTU值,如果没有这个参数,选用默认 route MTU,如果没有默认route,就设置成常量值 1500。
-p, --pidfile="/var/run/docker.pid" 后台进程PID文件路径
-r, --restart=true                  重启之前运行中的容器
-s, --storage-driver=""             强制容器运行时使用指定的存储驱动,例如,指定使用devicemapper, 可以这样:
                                    docker -d -s devicemapper
--selinux-enabled=false             启用selinux支持
--storage-opt=[]                    配置存储驱动的参数
--tls=false                         启动TLS认证开关
--tlscacert="/Users/dxiao/.docker/ca.pem"
                                    通过CA认证过的的certificate文件路径
--tlscert="/Users/dxiao/.docker/cert.pem"
                                    TLS的certificate文件路径
--tlskey="/Users/dxiao/.docker/key.pem"
                                    TLS的key文件路径
--tlsverify=false                   使用TLS并做后台进程与客户端通讯的验证
-v, --version=false                 显示版本信息
注意,其中带有[] 的启动参数可以指定多次,例如
    $ docker run -a stdin -a stdout -a stderr -i -t ubuntu /bin/bash

使用Docker部署Flask应用

Docker on Mac

1、Download boot2docker from http://get.daocloud.io or https://docs.docker.com/installation/mac/
2、Install for double click, then start boot2docker from Applications folder.
3、运行boot2docker会进行自动初始化,包括:
    - opens a terminal window
    - creates a $HOME/.boot2docker directory
    - creates a VirtualBox ISO and certs
    - starts a VirtualBox VM running the docker daemon
4、安装初始化界面中的提示,修改~/.bash_profile:
    export DOCKER_HOST=tcp://192.168.59.103:2376
    export DOCKER_CERT_PATH=/Users/ZG/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1
    $ source ~/.bash_profile
5、打开VirtualBox可以看到正在运行的boot2docker-vm
6、进入docker shell:
    boot2docker ssh
7、把本地代码文件映射到docker中的容器对应的路径,实现在本地编辑,在docker中执行,同理端口映射
8、编写Dockerfile来创建统一的开发、发布环境

参考