docker知识学习

docker的版本

docker分为2个版本,社区版本和企业版本。

  • Community Edition(CE)

  • Enterprise Edition(EE)

获取docker的ce版本

OS需求

  • 确保你启用的标准centos-extra仓库。

  • overlay2存储驱动推荐使用

卸载老版本的docker

$ sudo yum remove docker \
                docker-client \
                docker-client-latest \
                docker-common \
                docker-latest \
                docker-latest-logrotate \
                docker-logrotate \
                docker-selinux \
                docker-engine-selinux \
                docker-engine

备注

docker 社区版本的包名字为docker-ce,使用yum remove docker-ce完成卸载。

设置按照需要的仓库

$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

$ sudo yum-config-manager --enable docker-ce-edge
$ sudo yum-config-manager --enable docker-ce-test

安装docker

# 按照默认版本
$ sudo yum install docker-ce

# 按照指定版本
$ yum list docker-ce --showduplicates | sort -r
$ sudo yum install docker-ce-<VERSION STRING>

# 启动docker服务
$ sudo systemctl start docker

测试docker

# 运行一个hello world
$ sudo docker run hello-world

docker概念

docker是开发人员和系统管理员使用容器开发,部署和运行应用程序的平台。 使用linux容器部署应用程序称为容器化,用于快速部署应用程序。

docker优点

灵活

即使是最复杂的应用也可以集装箱化。

轻量级

容器利用并共享主机内核。

可互换

您可以即时部署更新和升级。

便携式

您可以在本地构建,部署到云,并在任何地方运行。

可扩展

您可以增加并自动分发容器副本。

可堆叠

您可以垂直和即时堆叠服务。

容器和镜像

一个容器是一个镜像的运行,一个镜像是一个可执行的包,这里面包含应用运行的代码、运行时环境、依赖库和配置文件等。 一个容器是一个镜像的运行实例,一个镜像可以运行处多个实例的。

容器和虚拟机

容器

虚拟机

_images/Container2x.png _images/VMx.png

docker版本

# 查看docker版本
docker --version
Docker version 17.12.0-ce, build c97c6d6

# 查看docker详细信息
docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 17.12.0-ce
Storage Driver: overlay2
...

测试docker的安装

# 运行一个样例docker
docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:ca0eeb6fb05351dfc8759c20733c91def84cb8007aa89a5bf606bc8b315b9fc7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

# 列出当前镜像列表
docker image ls

# 列出所有
docker container ls --all

CONTAINER ID     IMAGE           COMMAND      CREATED            STATUS
54f4984ed6a8     hello-world     "/hello"     20 seconds ago     Exited (0) 19 seconds ago

容器

需要的环境

  • docker>=1.13

部署环境

在过去,你如果部署一个python应用,你需要在你的计算机上安装python的运行时环境,且测试机器和生产环境还要一致的环境类型。 使用docker,你可以在应用程序的代码辅助python镜像,确保你的代码和运行时环境一起运行的。这些可一直的容器是由dockerfile定义的。

容器样例

创建docker文件

# 定义一个基础镜像
FROM python:2.7-slim

# 设置工作目录
WORKDIR /app

# copy当前目录到镜像的app目录
ADD . /app

# 使用pip安装软件
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# 暴露80端口为外部
EXPOSE 80

# 定义写环境变量
ENV NAME World

# 运行docker启动命令
CMD ["python", "app.py"]

准备requirements.txt文件

Flask
Redis

准备app.py文件

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
        "<b>Hostname:</b> {hostname}<br/>" \
        "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

构建

$ ls
Dockerfile          app.py                  requirements.txt

[root@iZ2ze3vsekthy9vqtndzefZ docker]# docker build -t friendlyhello .
Sending build context to Docker daemon 4.608 kB
Step 1/7 : FROM python:2.7-slim
Trying to pull repository docker.io/library/python ...
2.7-slim: Pulling from docker.io/library/python
be8881be8156: Pull complete
44247e56d488: Pull complete
ae1109c65233: Pull complete
97f741585990: Pull complete
Digest: sha256:9422cd48eb69711bb5feedbec8afd229f1409131f16daced947914938b37c811
Status: Downloaded newer image for docker.io/python:2.7-slim
---> 7302ff8cae7a
Step 2/7 : WORKDIR /app
---> ec5e5b5bb386
Removing intermediate container e4bc58b965b8
Step 3/7 : ADD . /app
---> 3039e0d44f67
Removing intermediate container 23019655d916
Step 4/7 : RUN pip install --trusted-host pypi.python.org -r requirements.txt
---> Running in bbf16703da30

Collecting Flask (from -r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)
Collecting Redis (from -r requirements.txt (line 2))
Downloading https://files.pythonhosted.org/packages/3b/f6/7a76333cf0b9251ecf49efff635015171843d9b977e4ffcf59f9c4428052/redis-2.10.6-py2.py3-none-any.whl (64kB)
Collecting itsdangerous>=0.24 (from Flask->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB)
Collecting Jinja2>=2.10 (from Flask->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
Collecting Werkzeug>=0.14 (from Flask->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
Collecting click>=5.1 (from Flask->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->Flask->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz
Building wheels for collected packages: itsdangerous, MarkupSafe
Running setup.py bdist_wheel for itsdangerous: started
Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5
Running setup.py bdist_wheel for MarkupSafe: started
Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
Successfully built itsdangerous MarkupSafe
Installing collected packages: itsdangerous, MarkupSafe, Jinja2, Werkzeug, click, Flask, Redis
Successfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.0 Redis-2.10.6 Werkzeug-0.14.1 click-6.7 itsdangerous-0.24
---> e3312707c13d
Removing intermediate container bbf16703da30
Step 5/7 : EXPOSE 80
---> Running in c70194d4650e
---> cec1a446cca8
Removing intermediate container c70194d4650e
Step 6/7 : ENV NAME World
---> Running in ed2b75276780
---> 7e5a33a4fc94
Removing intermediate container ed2b75276780
Step 7/7 : CMD python app.py
---> Running in 7ef196474b9e
---> 71c2acc4550b
Removing intermediate container 7ef196474b9e
Successfully built 71c2acc4550b

运行app

docker run -p 4000:80 friendlyhello

curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> e694031416cb<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

备注

上面docker run是默认运行在前台的,-d选项可以指定在后台运行。

关闭app

# 查看容器
docker container ls
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
    e694031416cb        friendlyhello       "python app.py"     2 minutes ago       Up 2 minutes        0.0.0.0:4000->80/tcp   relaxed_boyd

# 停掉容器
docker container stop e694031416cb

共享你的镜像

登陆dockerhub

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: zhaojiedi1992
Password:
Login Succeeded

备注

如果使用自己搭建的docker仓库, login后面跟网址就可以了。

给镜像打tag

docker image ls
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    friendlyhello                 latest              71c2acc4550b        2 hours ago         132 MB
    docker.io/python              2.7-slim            7302ff8cae7a        4 days ago          120 MB
    docker.io/busybox             glibc               0b09e1ac1503        13 days ago         4.42 MB
    docker.io/jolestar/go-probe   latest              cee847b51a27        5 weeks ago         36.8 MB

# 打tag
docker tag image username/repository:tag

推送镜像

docker tag friendlyhello zhaojiedi1992/helloworld:v1.0

拉取并运行自我镜像

docker run -p 4000:80 zhaojiedi1992/helloworld:v1.0

服务

需要的环境

  • docker>=1.13

  • docker compose

  • 已经完成前面2个章节

安装docker compose

# 配置k8s 仓库
[root@iZ2ze3vsekthy9vqtndzefZ yum.repos.d]# cat kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
    http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

# 开始安装
yum install docker-compose

备注

默认k8s的仓库是google的,没法访问的。

docker-compose.yml文件

编辑一个docker-compose.yml文件,内容如下:

version: "3"
services:
web:
    # replace username/repo:tag with your name and image details
    image: zhaojiedi1992/helloworld:v1.0
    deploy:
    replicas: 5
    resources:
        limits:
        cpus: "0.1"
        memory: 50M
    restart_policy:
        condition: on-failure
    ports:
    - "4000:80"
    networks:
    - webnet
networks:
webnet:

运行一个负载均衡的app


[root@iZ2ze3vsekthy9vqtndzefZ docker]# docker swarm init –advertise-addr 10.80.89.19

[root@iZ2ze3vsekthy9vqtndzefZ docker]# docker stack deploy -c docker-compose.yml getstartedlab Creating network getstartedlab_webnet Creating service getstartedlab_web

[root@iZ2ze3vsekthy9vqtndzefZ docker]# docker service ls ID NAME MODE REPLICAS IMAGE hf9hawqrchfq getstartedlab_web replicated 5/5 zhaojiedi1992/helloworld:v1.0

[root@iZ2ze3vsekthy9vqtndzefZ docker]# docker service ps getstartedlab_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS pv5j41ap4btg getstartedlab_web.1 zhaojiedi1992/helloworld:v1.0 iZ2ze3vsekthy9vqtndzefZ Running Running about a minute ago rsvlvfa48sk6 getstartedlab_web.2 zhaojiedi1992/helloworld:v1.0 iZ2ze3vsekthy9vqtndzefZ Running Running about a minute ago od33frib2yxs getstartedlab_web.3 zhaojiedi1992/helloworld:v1.0 iZ2ze3vsekthy9vqtndzefZ Running Running about a minute ago z2til8qa79k0 getstartedlab_web.4 zhaojiedi1992/helloworld:v1.0 iZ2ze3vsekthy9vqtndzefZ Running Running about a minute ago 29tnd4g7p8kj getstartedlab_web.5 zhaojiedi1992/helloworld:v1.0 iZ2ze3vsekthy9vqtndzefZ Running Running about a minute ago

扩展应用程序

修改docker-compose的集群数值,然后运行如下命令:

docker stack deploy -c docker-compose.yml getstartedlab

关闭app和swarm

docker stack rm getstartedlab
docker swarm leave --force

swarms

理解swarm集群

群集是一组运行Docker并加入群集的计算机。在此之后,您继续运行您习惯使用的Docker命令,但现在它们由群集管理器在群集上执行。 群中的机器可以是物理的或虚拟的。加入群组后,它们被称为节点。

Swarm管理器可以使用多种策略来运行容器,例如“最节点的节点” - 它使用容器填充利用率最低的机器。或“全局”,它确保每台机器只获得指定容器的一个实例。 您指示swarm管理器在Compose文件中使用这些策略,就像您已经使用的那样。

群集管理器是群中唯一可以执行命令的机器,或授权其他机器作为工作者加入群集。工人只是在那里提供能力,并且没有权力告诉任何其他机器它能做什么和不能做什么。

到目前为止,您一直在本地计算机上以单主机模式使用Docker。但是Docker也可以切换到swarm模式,这就是使用群集的能力。立即启用群集模式使当前计算机成为群集管理器。 从那时起,Docker就会运行您在管理的swarm上执行的命令,而不仅仅是在当前机器上。

设置swarm

管理端使用docker swarm init ,其他节点使用docker swarm join

网络概述

网络驱动程序

  • bridge: 这是默认的网络驱动程序

  • host: 删除容器和docker主机之间的网络隔离,直接使用主机的网络。

  • overlay: 覆盖网络将多个docker守护程序连接在一起,并使集群服务能够相互通信。

  • macvlan: 允许为容器分配mac地址。

  • none: 禁用所有网络。

  • 网络插件: 从第三方网络获取到的插件。

桥接网络

在网络方面,桥接网络是链路层设备,它在网络段之间转发流量。网桥可以是硬件设备火灾主机内核中运行的软件设备。

就docker而言,桥接网络使用软件桥接器,该软件桥接器允许连接到同一个桥接网络的容器之间进行通信,同事提供与未连接到桥接网络的容器隔离。

用户定义的网桥与默认网桥的差异

  1. 用户自定义的网桥在容器应用程序之间提供更好的隔离和互操作性。

  2. 用户自定义的网桥提供自动dns解析。

  3. 容器可以在运行中与用户定义的网络连接和分离。

  4. 用户定义的网络会创建一个可配置的网桥。

  5. 默认桥接网络上连接的容器共享环境变量。

管理用户定义的桥

创建

docker network create my-net

删除

docker network rm my-net

容器连接到这个网络

创建容器的时候连接到特定网络

docker create --name my-nginx --network my-net --publish 8080:80  nginx:latest

运行时链接到特定网络

docker network connect my-net   my-nginx

断开容器和自定义网络的连接

docker network disconnect my-net   my-nginx

覆盖网络

该overlay网络驱动程序会创建多个守护主机之间的分布式网络。该网络负载特定主机的网络之上,运行链接它的容器安全的进行通信。 docker透明地处理每个数据包与正确docker守护程序主机和正确的目标容器的路由。

使用覆盖网络,必须将docker初始化为swam模式(docker swarm init) ,会创建默认的ingress覆盖网络和docker_gwbridge接口 , docker_gwbrdge是一个虚拟网桥,将覆盖网络(包括ingress网络) 连接到单个docker守护程序的物理网络。

创建

docker network create -d overlay my-overlay
docker network create -的overlay --attachable my-attacheable-overlay

主机网络

如果采用host网络驱动,则该容器的网络堆栈不会与docker主机隔离。主机网络只支持linux主机。

macvlan网络

在某些应用程序,尤其是遗留应用程序或监事网络流量的应用程序,希望直接连接到物理网络,在这种情况下,您可以使用macvlan网络驱动程序为每个容器的虚拟网络接口分配 mac地址。

创建macvlan网络

docker network create -d macvlan \
--subnet=172.16.86.0/24 \
--gateway=172.16.86.1  \
-- parent=eth0 pub_net

none网络

如果要完全禁用容器上的网络堆栈,可以使用none网络,仅仅创建lo设备。

存储概述

默认情况下,在容器内创建的所有文件都存储在可写的容器层。

确保容器定制之后存储的可用性,可以采用卷或者绑定挂载方式,在linux环境下还可以使用tmpfs挂载方式。

卷存储由docker管理的主机文件系统的一部分中,非docker进程不应该修改文件系统的这一个部分,卷是保留数据的最佳方式。

绑定挂载

绑定挂载可以存储在主机系统的任何位置,他们甚至可能是重要的系统文件或者目录,docker主机或者docker容器上的非docker进程是可以随时修改他们的。

tmpfs

tmp挂载方式存储在主机的系统内存中,永远不会写入主机系统的文件系统中。

三种存储方式比较

存储方式比较

volume

bind

tmpfs

应用场景

生产环境

开发环境

临时存储不想放到容器可写层的敏感文件挂载

平台支撑

所有平台

所有平台

只在linux平台

cli或者api管理支撑

支撑

不支持

不支持

多容器共享支撑

支撑

支撑

支撑

卷是保存docker容器生成和使用数据的首选机制,卷完全由docker管理。

卷通常是持久数据最好的选择,因为卷不会增加使用它的容器大小,并且卷的内容存在给定容器的生命周期之外。

卷挂载优点

  1. 更容易备份或者迁移

  2. 可以使用cli或者api管理卷。

  3. 使用与windows和linux环境。

  4. 可以在多个容器之间安全共享卷。

  5. 卷驱动程序运行您在远程主机或者云提供程序上存储卷。

  6. 新卷可以通过容器预先填充其内容。

创建和管理卷

# 创建卷
docker volume create my-vol
# 获取卷详细信息
docker volume inspect my-vol
# 删除卷
docker volume rm my-vol
docker run -d --name devtest --mount source=my-vol,target=/app nginx:latest

备注

建议使用–mount 方式挂载

如果挂载的卷是空的目录, 然后目标容器的特定目录是有内容的, 这样在启动的时候挂载过去的时候, 这个卷会被目标容器的内容填充的。

使用卷备份或者迁移数据

备份

docker run --rm --volume-from dbstore -v $(pwd):/backup   ubuntu tar cvf /backup/backup.tar /dbdata

还原容器

docker run  -v /dbdata --name dbstore2 ubuntu /bin/bash
docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xf /backup.tar "

绑定挂载

在docker早期,绑定挂载就是一直存在的,绑定主机上的文件或者目录到容器中去。

具体的挂载和卷类型,只是类型指定为bind即可。

如果板顶到容器上的飞空目录中,则绑定会隐藏目录现有的内容。

tmpfs挂载

卷挂载和绑定挂载能让你在主机和容器之间共享文件, 以便即使在容器停止后也是可以保留数据的。

如果在linux环境下,还是可以使用第三种挂载方式,tmpsfs mount 。 tmpfs挂载是临时的,并且仅仅保留在主机内存中,当 容器停止后,tmpfs会被删除安装,并且不会保留卸载挂载目录的文件。

应用场景: 对于临时存储但不希望在容器可写层保留的敏感文件很有用。

具体的挂载和卷类型, 只是类型选择tmpfs即可,建议制定可使用的文件大小(tmpfs-size)。

docker部署最佳实践

如何让你的镜像更小

  • 选择合适的基础镜像,如果你需要jdk环境,建议直接选择openjdk作为基础镜像,而不是选择ubuntu镜像后按照openjdk在dockerfile中。

  • 使用多级构建,多条相同命令合并为一条命令,减少构建层级。

  • 如果多个镜像有大量相同的功能,可以考虑根据相同的功能创建一个基础镜像。

  • 为了保持生产镜像的精简,你可以创建一个精简镜像,以精简镜像为基础镜像安装调试工具包。

  • 构建镜像,总是使用tags进行编写描述信息。

怎么让数据持久化

  • 避免使用容器的存储,使用卷或者绑定挂载功能。

  • 开发期间可以使用bind mount来挂载需要的挂载二进制文件到容器中,生产环境请使用卷。

  • 对于生产,加密重要信息,使用configs配置非机密配置文件。

尽可能使用swarm服务

使用CI/CD去测试和部署

  • 当您检查对源代码管理的更改或创建拉取请求时,请使用Docker Cloud或其他CI / CD管道自动构建和标记Docker镜像并对其进行测试。

开发和生产采用不同环境

  • 开发采用bind mounts ,生产采用卷。

  • 开发不用关心时间同步信息,生产环境一个集群确保采用同一个ntp server。

dockerfile编写最佳实践

一般准则和建议

  • 创建尽可能精简的容器

  • 了解构建上下文

  • 通过stdin管道Dockerfile

  • 包含dockerignore文件

  • 使用多阶段构建

  • 不要安装不必要的包

  • 解构应用程序,分离容器功能,每个容器限制为单个进程,保存容器的清洁和模块化,容器直接可以通过网络通信。

  • 最小化层级

  • 一个命令可以使用转义为多行,美化dockerfile文件。让别人看起来舒服点。

  • 利用构建缓存

通过stdin管道Dockerfile的样例

docker build -t foo -<<EOF
FROM busybox
RUN echo "hello world"
EOF

docker指令

FROM

尽量选择alpine镜像作为源镜像,这样构建的镜像才最小

LABEL

LABEL用来说明我们的镜像信息的,尽可能的详细点。

比较详细的dockerfile label

# Set one or more individual labels
LABEL com.example.version="0.0.1-beta"
LABEL vendor1="ACME Incorporated"
LABEL vendor2=ZENITH\ Incorporated
LABEL com.example.release-date="2015-02-12"
LABEL com.example.version.is-production=""

但是上面的label会构建多层的。需要改进为如下风格的。

LABEL vendor=ACME\ Incorporated \
    com.example.is-beta= \
    com.example.is-production="" \
    com.example.version="0.0.1-beta" \
    com.example.release-date="2015-02-12"

RUN

使用来分割命令为多行,来增加可读性和可维护性。

USING PIPES

docker使用/bin/sh -c来解释run命令,该解释器仅仅评估管道中最后一个的操作码来确定成功,

# 即使wget失败,后续的wc -l成功,整句的就是成功的。
RUN wget -O - https://some.site | wc -l > /number

CMD

CMD 尽可能采用数组形式的,且只提供参数,具体的命令使用ENDPOINT指定。

EXPOSE

ENV

为了确保你的应用程序以比较简单的方式去运行,可以使用env去添加环境变量。

ENV PATH /usr/local/nginx/bin:$PATH
CMD ["nginx"]

每个ENV会添加一层,可以一次添加多个行间变量。可以使用run来替代ENV

FROM alpine
RUN export ADMIN_USER="mark" \
    && echo $ADMIN_USER > ./mark \
    && unset ADMIN_USER
CMD sh

ADD or COPY

ADD和COPY都可以完成文件的copy工作。 但是ADD可以下载网络资源,并可以自动完成解压到特定目录去。 强烈建议不要使用ADD从远程URL中获取包。 你应该使用curl或wget代替,样例如下。

错误做法:


ADD http://example.com/big.tar.xz /usr/src/things/ RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things RUN make -C /usr/src/things all

替代做法:

RUN mkdir -p /usr/src/things \
    && curl -SL http://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all

备注

如果不需要add的自动解压功能,你应该始终使用COPY。

ENTRYPOINT

ENTRYPOINT用于定义程序的主命令,CMD用来定义给ENTRYPOINT的参数,且2中都采用数组形式。

exec用于执行一个新命令去替换现有进程,可以保证我们的进程启动在pid为1 。

VOLUME

使用卷去存储数据库数据,或者配置文件等。

USER

可以指定一个非root的用户作为容器的运行身份。

WORKDIR

写WORKDIR请采用绝对路径,采用相对路径会增加维护和故障排查问题。

ONBUILD

ONBUILD命令是执行在当前dockefile构建完毕的镜像被别人作为基础镜像后的执行脚本。

创建一个基础镜像

使用多步构建

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

dockerfile参考

使用

docker build
docker build -t zhaojiedi1992/helloworld:v1.0 -t zhaojiedi1992/helloworld:latest  -f  -f /path/to/a/Dockerfile .

注释

dockefile中注释使用#开头。

# 这是一个注释行

转义

dockerfile中使用来转义空格、换行符等。

环境变量替换

环境变量通过ENV指定,支持bash操作的。比如${foo},${foo-abc}等

可以使用环境变量的片段为:

  • ADD

  • COPY

  • ENV

  • EXPOSE

  • FROM

  • LABEL

  • STOPSIGNAL

  • USER

  • VOLUME

  • WORKDIR

备注

在1.4版本之后,ONBUILD也支持使用环境变量了。

.dockerignore文件

dockerfile 主要配合add,copy使用,包含在dockerignore的配置被过滤掉的。具体的语法类似gitignore文件。

FROM

FROM用于指定基础镜像的名字。

用法:

FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]

使用样例

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

ARG不同于ENV的,ARG作用于docker命令构建的时候,ENV是在镜像构建后,实例化的时候运行的。

RUN

RUN有2种格式用法

RUN <command>
RUN ["executable", "param1", "param2"]

CMD

CMD有三种格式用法。

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

LABEL

LABEL用于定义描述信息。是一个key,value对

用法:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

定义的LABEL信息,可以通过docker inspect命令获取镜像的LABEL信息。

MAINTAINER (已经弃用了)

使用如下设置维护者。

LABEL maintainer="SvenDowideit@home.org.au"

EXPOSE

用于指定需要暴露的的端口,用法:

EXPOSE <port> [<port>/<protocol>...]

样例:

EXPOSE 80/tcp
EXPOSE 80/udp

我们可以在docker运行时重设这些设置信息。

docker run -p 80:80/tcp -p 80:80/udp ...

ENV

用于定义运行时的变量

ENV <key> <value>
ENV <key>=<value> ...

样例:

ENV myName="John Doe" myDog=Rex\ The\ Dog \
    myCat=fluffy

ADD

用于从当前的目录复制文件到镜像中去

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

COPY

用于从当前的目录复制文件到镜像中去

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

ENTRYPOINT

ENTRYPOINT用于定义进入点,用法2种。

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

样例:

FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

如果docker运行的时候想重写ENTRYPOINT,可以指定–entrypoint 选项。

ENTRYPOINT 和CMD

ENTRYPOINT “ENTRYPOINT exec_entry p1_entry”

ENTRYPOINT [exec_entry, p1_entry]

No CMD

error, not allowed

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry

CMD [exec_cmd, p1_cmd]

exec_cmd p1_cmd

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry exec_cmd p1_cmd

CMD [p1_cmd, p2_cmd]

p1_cmd p2_cmd

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry p1_cmd p2_cmd

CMD exec_cmd p1_cmd

/bin/sh -c exec_cmd p1_cmd

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

VOLUME

用于设置卷,用法:

VOLUME ["/data"]

USER

设置运行的用户身份,用法:

USER <user>[:<group>] or
USER <UID>[:<GID>]

WORKDIR

设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD都是有影响的。

样例:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

上面的打印结果为/a/b/c的。

ARG

ARG用于指定参数,用法:

ARG <name>[=<default value>]

样例:

docker build --build-arg <varname>=<value>
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER

ONBUILD

ONBUILD会在此镜像作为其他镜像的基础镜像的时候被执行。

构建步骤:

  1. 当遇到ONBUILD指令时,构建器会向正在构建的镜像的元数据添加触发器。 该指令不会影响当前构建。

  2. 在构建结束时,所有触发器的列表都存储在映像清单中的OnBuild键下。 可以使用docker inspect命令检查它们。

  3. 稍后,可以使用FROM指令将镜像用作新构建的基础。 作为处理FROM指令的一部分,下游构建器查找ONBUILD触发器,并按照它们注册的顺序执行它们。 如果任何触发器失败,则中止FROM指令,这反过来导致构建失败。 如果所有触发器都成功,则FROM指令完成,并且构建继续照常进行。

  4. 执行后,触发器将从最终镜像中清除。

样例:

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

STOPSIGNAL

设置发送的信号。

STOPSIGNAL SIGKILL

HEALTHCHECK

提供健康检查功能,用法:

HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE

    # 选项有
    --interval=DURATION (default: 30s)
    --timeout=DURATION (default: 30s)
    --start-period=DURATION (default: 0s)
    --retries=N (default: 3)

SHELL

指定shell的,用法。

SHELL ["executable", "parameters"]
# 在linux下为  ["/bin/sh", "-c"]
# 在window下为 ["cmd", "/S", "/C"]

docker run

docker run 提供直接运行一个容器。

一般形式

$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

主要选项

-d 后台运行 -a 附件到标准输出流 -t 分配一个pseudo-tty -i 保持STDIN打开的 –restart 重启策略 –rm 停止后删除容器 –network 设置网络 –cidfile 写入容器id到特定文件中 –pid 设置pid命令空间模式 –dns 指定dns –network-alias 网络别名 –add-hosts 添加一行到/etc/hosts –mac-address 指定mac地址 –ip 设置ip -m 内存限制 –memory-swap 总呢次限制 -c cpu份额 –cpuset-cpus 允许指定的cpu –privileged 特权模式 –log-driver 日志驱动类型 –entrypoint 指定运行时的默认值 -p 暴露特定端口 -e 指定环境变量 –tmpfs 挂载tmpfs文件系统 -v 挂载卷 –volume-from 和特定容器挂载一样的卷 -u 指定用户 -w 工作目录设置

使用docker 命令行

docker中的优先级 命令行指定 > 环境变量 > config.json

获取帮助信息

docker run --help
docker container ls --help

命令

描述

docker attach

将本地标准的输入输出和错误流附加到正在运行的容器上面

docker bulid

从dockerfile构建镜像

docker checkpoint

管理检查点

docker commit

根据容器的更改创建新的镜像

docker config

管理docker的配置

docker container

管理容器

docker cp

在容器和本地文件系统之间复制文件或者文件夹

docker create

创建一个新的容器

dokcer deploy

部署或者更新

docker diff

检查容器文件系统的文件或者目录的更改

docker envents

获取服务器的实时事件

docker exec

在正在运行的容器中运行命令

docker export

将容器的文件系统导出为tar归档

docker history

显示镜像的提交历史

docker image

管理镜像

docker images

列出镜像

docker import

从tar包导入内容创建新的镜像

dokcer info

获取docker基本信息

docker inspect

获取docker特定对象的详细信息

docker kill

杀掉特定容器

docker load

从tar包加载镜像或者stdin加载

docker login

登陆,默认是dockerhub

docker logout

注销

docker logs

获取容器的日志信息

docker manifest

管理docker镜像清单

docker network

管理docker网络

docker node

管理swam节点

docker pause

暂停容器

docker port

管理端口

docker ps

列出容器

docker pull

拉取镜像

docker push

提交镜像

docker rename

重命名

docker restart

重启容器

docker rm

删除容器

docker rmi

删除镜像

docker run

运行容器

dokcer save

保持容器

docker search

从dockerhub搜索镜像

docker service

管理服务

docker stack

管理堆栈

docker stats

获取统计信息

docker stop

停止容器

docke swarm

管理swarm

docker system

管理docker

docker tag

打tag信息

docker top

获取top信息

docker trust

管理对docker镜像的信任

docker update

更新

docker version

获取版本信息

docker volume

管理卷

docker wait

等待容器停止,然后打印退出码

docker基础字命令

docker attach

docker attach 用于将本地标准的输入、输出和错误流附加到正在运行的容器上。

使用attach到特定容器后,使用`ctrl+c` 发送kill信号的, 会导致容器被杀掉。 如果指定了–sig-proxy为true的时候,则发送int信号, 你可以使用ctrl+p+q来保持继续运行。

docker build

docker build 从dockerfile构建镜像。

用法

docker build [OPTIONS] PATH | URL | -

其中url可以是git仓库和tar和纯文本文件。

样例

docker build https://github.com/docker/rootfs.git#container:docker
docker build .
docker build - < Dockerfile
docker build -f ctx/Dockerfile http://server/ctx.tar.gz

docker checkpoint

docker checkpoint 是创建检查点的,实验功能。

创建用法

docker checkpoint create [OPTIONS] CONTAINER CHECKPOINT

查看用法

docker checkpoint ls [OPTIONS] CONTAINER

删除用法

docker checkpoint rm [OPTIONS] CONTAINER CHECKPOINT

docker commit

docker commit 根据容器的更改创建新的镜像

将容器的修改护着设置提交到新镜像上, 您可以在镜像导出到另一个服务器上,进行问题的调试和解决。 最好使用dockerfiles以文档化和可维护的方式管理镜像。

用法

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

样例

docker container ls
docker commit c3f279d17e0a  svendowideit/testimage:v3
docker image ls

docker config

docker config 提供docker配置的管理工作。

docker container

docker container 提供容器管理。

字命令

  • docker container attach

  • docker container commit

  • docker container cp

  • docker container create

  • docker container diff

  • docker container exec

  • docker container export

  • docker container checkpoint

  • docker container kill

  • docker container log

  • docker container ls

  • docker container pause

  • docker container port

  • docker container prune

  • docker container restart

  • docker container rm

  • docker container run

  • docker container start

  • docker container stats

  • docker container unpause

  • docker container update

  • docker container wait

docker cp

docker cp 提供容器和本地文件系统之间复制文件或者文件夹功能。

用法

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

cp的使用和unix的cp基本类似,-a保留权限。

docker build

docker build 用于根据dockerfile构建一个镜像。

支持的构建来源包括url,git仓库,本地路径等。

docker deploy

部署新堆栈或更新现有堆栈

docker diff

docker diff 检查容器文件系统上的文件或者目录的更改。

用法

docker diff container

变化类型有3种,A表示添加,D表示删除,C表示更改。

docker event

docker event 提供从服务器获取实时事件。

docker exec

docker exec 在运行的容器中运行命令。

用法

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

主要选项

-t

分离模式

-e

设置环境变量

-i

交互

-t

分配tty

备注

command应该是可执行文件,不能是带引号的命令。

docker export

docker export 将容器的文件系统导出为tar归档。

用法

docker export [OPTIONS] CONTAINER

选项只有一个`-o`来指定数据的位置。

样例

docker export red_panda > latest.tar
docker export -o latest.tar red_panda

docker history

docker history 显示一个镜像的历史

用法

docker history [OPTIONS] IMAGE

样例

docker history --format "{{.ID}}: {{.CreatedSince}}" busybox

docker images

docker images 列出镜像列表

用法

docker images [OPTIONS] [REPOSITORY[:TAG]]

样例

docker history --format "{{.ID}}: {{.CreatedSince}}" busybox
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"

docker import

docker import 从tar包导入内容以创建文件系统镜像。

用法

docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

选项

-c

将dockerfile指令应用到创建的镜像

-m

为导入的图形设置提交信息

样例

docker import http://example.com/exampleimage.tgz
cat exampleimage.tgz | docker import - exampleimagelocal:new
docker import -m "init"  /path/to/exampleimage.tgz
sudo tar -c . | docker import - exampleimagedir

docker info

docker info 显示docker系统范围的信息。

用法

docker info [OPTIONS]

样例

docker info --format '{{json .}}'

docker inspect

docker inspect 获取docker对象的基础信息。

用法

docker inspect [OPTIONS] NAME|ID [NAME|ID...]

样例

docker inspect --format='{{json .Config}}' $INSTANCE_ID
docker inspect --format='{{.Config.Image}}' $INSTANCE_I