Docker 基础培训 - 使用 Docker

1 基础概念

Docker 包括三个基本概念

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

1.1 Docker 镜像

镜像就是一个只读的模板(可以认为是个虚拟CD盘),上面可以安装一整套ubuntu操作系统,也可以只安装了一个应用程序。镜像是只读的。

1.2 Docker 容器

利用镜像创建的一个运行环境的实例(可以认为是一个运行中的简化版虚拟机,包括root用户权限、进程空间、用户空间和网络空间等)。

1.3 Docker 仓库

ku

仓库是集中存放镜像文件的场所。有时候会把仓库(Repository)和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

2 Docker 安装

2.1 安装前注意

现有docker还在飞速发展中,新版本层出不穷,为了避免兼容性问题,我公司产品定义只兼容docker 1.7.1以上版本。故此,请检查系统版本:

  • centos 7.0以上
  • ubuntu 14.04以上

2.2 Ubuntu

安装脚本

  1. $ sudo apt-get install apt-transport-https
  2. $ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
  3. $ sudo bash -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
  4. $ sudo apt-get update
  5. $ sudo apt-get install lxc-docker

安装后应该直接启动,如果没有使用下面命令启动即可

  1. $ sudo service docker start

2.3 Centos

安装脚本

  1. $ sudo yum install docker

安装后应该直接启动,如果没有使用下面命令启动即可

  1. $ sudo service docker start
  2. $ sudo chkconfig docker on

3 Docker 镜像操作

3.1 获取镜像

使用docker pull命令获取镜像。

从 Docker Hub 获取 base 镜像 ubuntu 系统,版本12.04

下载过程中,会获取镜像的每一层信息,以下命令相当于执行了$ sudo docker pull registry.hub.docker.com/ubuntu:12.04

  1. $ sudo docker pull ubuntu:12.04
  2. Pulling repository ubuntu
  3. ab8e2728644c: Pulling dependent layers
  4. 5f0ffaa9455e: Download complete
  5. a300658979be: Download complete
  6. 904483ae0c30: Download complete
  7. ....

其他仓库下载

  1. $ sudo docker pull regsitry.shurenyun.com:5000/ubuntu:12.04
  2. Pulling regsitry.shurenyun.com:5000/ubuntu
  3. ab8e2728644c: Pulling dependent layers
  4. 511136ea3c5a: Download complete
  5. 5f0ffaa9455e: Download complete
  6. a300658979be: Download complete
  7. ....

3.2 列出本地镜像

使用docker images显示本地已有的镜像。

  1. $ sudo docker images
  2. REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
  3. ubuntu 14.04 99ec81b80c55 4 weeks ago 266 MB
  4. ...

参数描述

  1. REPOSITORY 来自于哪个仓库,什么软件比如 ubuntu
  2. TAG 镜像标记,比如 14.04
  3. IMAGE ID 镜像ID 号(唯一)
  4. CREATED 创建了多久
  5. VIRTUAL SIZE镜像大小

3.3 创建镜像

创建镜像通常有两种方法:

  • 用现有镜像加内容生成新镜像

  • 用dockerfile生成新镜像

现有镜像生成

先使用现有镜像启动容器

  1. $ sudo docker run -t -i ubuntu:14.04 /bin/bash
  2. root@0b2616b0e5a8:/#

记住容器的 ID:0b2616b0e5a8,并按照对应linux方法安装应用

  1. root@0b2616b0e5a8:/# yum -y install nginx

安装结束后,使用exit退出容器,然后使用docker commit命令提交新的镜像。

  1. $ sudo docker commit -m "Added nginx" -a "Docker pro" 0b2616b0e5a8 ubuntu/nginx:v1
  2. 4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c

参数描述

  1. -m 来指定提交的说明信息,跟我们使用的版本控制工具一样;
  2. -a 可以指定更新的用户信息;
  3. 0b2616b0e5a8 是用来创建镜像的容器实例ID
  4. ubuntu/nginx:v1 指定目标镜像的仓库名和 tag 信息。
  5. 4f177bd27a9ff... 创建成功后会返回这个镜像的 ID 信息。

dockerfile 生成

和刚才一样用docekrfile重做一遍,首先生成dockerfile文件

  1. mkdir -p /data/tools/nginx/ && cd /data/tools/nginx/
  2. vi Dockerfile
  3. # This is a comment
  4. FROM ubuntu:14.04
  5. MAINTAINER Docker pro <pro@xxx.com>
  6. RUN apt-get update
  7. RUN apt-get -qqy install nginx

参数描述

  1. 使用#来注释
  2. FROM 指令告诉 Docker 使用哪个镜像作为基础
  3. MAINTAINER 是维护者的信息
  4. RUN 开头的指令会在创建中运行,比如安装一个软件包,在这里使用 apt-get 来安装了一些软件

文件写完后退出编辑文件,生成镜像

  1. sudo docker build -t ubuntu/nginx:v1 .
  2. Uploading context 2.56 kB
  3. Uploading context
  4. Step 0 : FROM ubuntu:14.04
  5. ---> 99ec81b80c55
  6. ...
  7. ---> 324104cde6ad
  8. Removing intermediate container 5e9d0065c1f7
  9. Successfully built 324104cde6ad

参数说明

  1. -t 标记来添加 tag,指定新的镜像的用户信息。
  2. “.” Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径。

上传镜像
用户可以通过docker push命令,默认推到dockerhub上

  1. $ sudo docker push ubuntu/nginx:v1
  2. The push refers to a repository [ubuntu/nginx:v1] (len: 1)
  3. Sending image list
  4. .....

3.4 导出导入镜像

使用docker save -o将镜像导出成tar

  1. sudo docker save -o ubuntu_14.04.tar ubuntu:14.04

使用docker loadtar包导入镜像

  1. sudo docker load --input ubuntu_14.04.tar
  2. or
  3. sudo docker load < ubuntu_14.04.tar

3.5 移除镜像

使用docker rmi命令移除本地镜像,注意docker rm移除的是容器实例。在删除镜像之前要先用docker rm删掉依赖于这个镜像的所有容器。

  1. $ sudo docker rmi ubuntu/nginx:v1

4 容器实例操作

4.1 启动容器实例

启动容器分两种情况,第一种是新建启动,第二种是关闭实例启动。

新建启动

使用docker run启动容器实例,分2种情况

1 命令输出一个 “Hello World”,之后终止容器

  1. $ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
  2. Hello world

2 启动一个 bash 终端,允许用户进行交互

  1. $ sudo docker run -t -i ubuntu:14.04 /bin/bash
  2. root@af8bae53bdd3:/#

参数说明

  1. -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
  2. -i 则让容器的标准输入保持打开。

关闭实例启动

使用docker start启动关闭实例
查看关闭实例

  1. docker ps -a
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 8e712339857b centos7/jdk8/jenkins1.628/base "/bin/bash" 4 days ago Exited (137) 5 seconds ago jenkins

启动关闭实例

  1. docker start jenkins

4.2 守护进程启动(后台运行)

Docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现。

对比测试

不使用-d参数,结果(STDOUT)打印到宿主机上面

  1. sudo docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
  2. hello world
  3. hello world
  4. hello world
  5. ......

使用了-d参数运行容器

  1. $ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
  2. 77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a

使用docker ps命令来查看容器信息

  1. $ sudo docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 77b2dc01fe0f ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright

通过docker logs命令查看容器日志

  1. $ sudo docker logs [container ID or NAMES]
  2. hello world
  3. hello world
  4. ....

4.3 终止容器实例

可以使用docker stop来终止一个运行中的容器,如果是使用非后台模式启动的容器,也可以使用exit或者Ctrl+D来退出中断终止容器。
使用docker ps命令来查看容器信息

  1. $ sudo docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 77b2dc01fe0f ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright

使用docker stop来终止这个容器

  1. $ sudo docker stop CONTAINER ID or NAMES

当然也可以使用docker restart来重启这个容器

  1. $ sudo docker restart CONTAINER ID or NAMES

4.4 进入容器实例

-d参数容器进入后台运行后,某些时候需要进入容器进行操作,有很多种方法,包括使用docker attach命令或docker exec等。
使用docker ps命令来查看容器信息

  1. $ sudo docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 77b2dc01fe0f ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright

docker attach

使用docker attach时,程序会打开-d程序的前端(开发、测试环境使用,严禁生成产使用)

  1. $ sudo docker attach 77b2dc01fe0f

如果Ctrl+D关闭,原先的程序会关闭

  1. $ sudo docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

docker exec

使用docker exec时,程序会打开运行容器的另一个bash环境,这样在退出时就不会影响到之前docker run的程序了.

  1. $ sudo docker exec -it 77b2dc01fe0f /bin/bash
  2. [root@77b2dc01fe0f /]# exit
  3. $ sudo docker ps
  4. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  5. 77b2dc01fe0f ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright

4.5 容器实例快照导入导出

导出容器实例

使用docker export命令,注意容器实例要关闭状态

  1. $ sudo docker ps -a
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 7691a814370e ubuntu:14.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test
  4. $ sudo docker export 7691a814370e > ubuntu.tar

导入容器实例快照

可以使用docker import从容器快照再导入镜像

  1. $ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0
  2. $ sudo docker images
  3. REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
  4. test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB

远程导入

  1. $sudo docker import http://example.com/exampleimage.tgz example/imagerepo

4.5 删除实例

可以使用 docker rm删除实例,删除一个终止状态的容器实例

  1. $sudo docker rm trusting_newton
  2. trusting_newton

也可以增加-f参数来删除一个运行中的容器实例

  1. $sudo docker rm -f trusting_newton
  2. trusting_newton

5 仓库

5.1 Docker Hub

目前 Docker 官方维护了一个公共仓库 Docker Hub,其中已经包括了超过 15,000 的镜像。大部分需求,都可以通过在 Docker Hub 中直接下载镜像来实现。

登录

可以通过docker login来登录,输入账户密码邮箱后完成注册和登录,登录后会在本地用户目录生成一个.dockercfg用户认证信息文件。

基本操作

使用docker search来查询 Docker Hub 中的镜像,并可以使用docker pull下载到本地。

  1. $ sudo docker search centos
  2. NAME DESCRIPTION STARS OFFICIAL AUTOMATED
  3. centos The official build of CentOS. 465 [OK]
  4. ...

参数名

  1. NAME 镜像的名字
  2. DESCRIPTION 镜像描述
  3. STARS 欢迎程度
  4. OFFICIAL 是否是官方提供镜像
  5. AUTOMATED 是否允许用户验证镜像内容和来源

使用docker pull下载镜像到本地

  1. $ sudo docker pull centos
  2. Pulling repository centos
  3. 0b443ba03958: Download complete
  4. 539c0211cd76: Download complete
  5. ....

5.2 私有仓库

启动私有仓库

有的时候公共仓库不方便,用户可以在本地创建一个私有库,使用官方提供的registry镜像创建。默认情况下,仓库会被创建在容器的 /tmp/registry 下,通过-v参数来指定本地磁盘存储

  1. $ sudo docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry

上传镜像

将镜像tag修改

  1. $ sudo docker images
  2. REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
  3. ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB
  4. ubuntu 14.04 ba5877dc9bec 6 weeks ago 192.7 MB

使用docker tagba58这个镜像标记为192.168.7.26:5000/test

  1. $ sudo docker tag ba58 192.168.7.26:5000/test
  2. root ~ # docker images
  3. REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
  4. ubuntu 14.04 ba5877dc9bec 6 weeks ago 192.7 MB
  5. ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB
  6. 192.168.7.26:5000/test latest ba5877dc9bec 6 weeks ago 192.7 MB

使用docker push上传标记的镜像

  1. $ sudo docker push 192.168.7.26:5000/test
  2. The push refers to a repository [192.168.7.26:5000/test] (len: 1)
  3. Sending image list
  4. Pushing repository 192.168.7.26:5000/test (1 tags)
  5. Image 511136ea3c5a already pushed, skipping
  6. Image 9bad880da3d2 already pushed, skipping
  7. ...
  8. Pushing tag for rev [ba5877dc9bec] on {http://192.168.7.26:5000/v1/repositories/test/tags/latest}

查询镜像

curl查看仓库中的镜像。

  1. $ curl http://192.168.7.26:5000/v1/search
  2. {"description": "", "name": "dockerfile/ubuntu"}, {"description": "", "name": "library/test"}]}

下载镜像

到另外一台机器使用docker pull下载

  1. $ sudo docker pull 192.168.7.26:5000/test
  2. Pulling repository 192.168.7.26:5000/test
  3. ba5877dc9bec: Download complete
  4. ....
  5. $ sudo docker images
  6. REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
  7. 192.168.7.26:5000/test latest ba5877dc9bec 6 weeks ago 192.7 MB

6 数据卷

数据卷的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷。有以下特性。

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除

6.1 生成一个数据卷

在用docker run命令的时候,使用-v标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。

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

6.2 删除数据卷

删除容器的时候使用docker rm -v这个命令

6.3 挂载一个主机目录作为数据卷

使用-v标记也可以指定挂载一个本地主机的目录到容器中去。

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

6.4 挂载卷只读

Docker 挂载数据卷的默认权限是读写,用户也可以通过 :ro 指定为只读。

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

6.5 查看数据卷的具体信息

使用docker inspect查看具体信息

  1. $ docker inspect web
  2. ...
  3. "Volumes": {
  4. "/webapp": "/var/lib/docker/volumes/fac362...80535"
  5. },
  6. "VolumesRW": {
  7. "/webapp": true
  8. }
  9. ...

6.6 挂载一个本地主机文件作为数据卷

-v标记也可以从主机挂载单个文件到容器中

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

6.7 挂载数据盘到其他节点

创建一个名为 dbdata 的数据卷容器:

  1. $ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

其他容器中使用 —volumes-from 来挂载 dbdata 容器中的数据卷。

  1. $ sudo docker run -d --volumes-from dbdata --name db1 training/postgres
  2. $ sudo docker run -d --volumes-from dbdata --name db2 training/postgres

从其他已经挂载了数据卷的容器来级联挂载数据卷

  1. $ sudo docker run -d --name db3 --volumes-from db1 training/postgres

6.8 备份数据卷

使用 —volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从主机挂载当前目录到容器的 /backup,并备份/data挂载数据卷数据。

  1. $ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

6.9 恢复

创建一个带有空数据卷的容器 dbdata2

  1. $ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

创建另一个容器,挂载 dbdata2 容器卷中的数据卷,并使用 untar 解压备份文件到挂载的容器卷中。

  1. $ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

再启动一个容器挂载同样的容器卷来查看

  1. $ sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata

7 网络

容器可以使用 -P 或 -p 参数来指定端口映射

7.1 映射49000~49900随机端口(非服务端口)

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

参数

  1. -P(大) 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。

7.2 映射指定端口

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

参数

  1. -p (小)使用 ip:hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口

7.3 映射到指定地址的任意端口

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

参数

  1. -p (小)使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口

7.4 udp端口

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

7.5 查看映射端口

使用docker port查看当前映射端口

  1. $ docker port nostalgic_morse 5000
  2. 127.0.0.1:49155.

7.6 容器互联

如果多个容器实例在同一台机器上启动,就可以使用--link进行互联

使用--name标记可以为容器自定义命名。

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

创建web服务并连接到db容器实例

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

参数介绍

  1. --link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。

使用docker ps来查看容器的连接

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

Docker 在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动 db 容器的时候并没有使用 -p 和 -P 标记,从而避免了暴露数据库端口到外部网络上。