苏苏的博客

简约至极

开启docker之旅

安装Docker

docker 安装需要Linux内核在3.10.0以上,仅支持Linux,在Windows和MacOs上也是基于虚拟机方式运行,需要提前安装虚拟机

OpenVZ的VPS内核版本较低,且不能升级,并不能作为docker server,但是可以使用docker client

  • 通过df -lhT 看到Type为simfs,而不是ext3,ext4,一般就代表使用的是OpenVZ虚拟化的
  • 查看系统内核版本uname -r

查看安装的系统版本 lsb_release -a 或者 cat /etc/issue

以下二种方法适用于RedHat,CentOS

  • cat /etc/redhat-release 或者 cat /etc/centos-release
  • rpm -q centos-release 或者 rpm -q redhat-release

查看是否是64位系统uname -i

下载安装

http://www.oschina.net/news/83328/docker-17-03-1-ce-released

deb/rpm install: curl -fsSL https://get.docker.com/ | sh

Linux 64bits tgz: https://get.docker.com/builds/Linux/x86_64/docker-17.03.1-ce.tgz

Darwin/OSX 64bits client tgz: https://get.docker.com/builds/Darwin/x86_64/docker-17.03.1-ce.tgz

Linux 32bits arm tgz: https://get.docker.com/builds/Linux/armel/docker-17.03.1-ce.tgz

Windows 64bits zip: https://get.docker.com/builds/Windows/x86_64/docker-17.03.1-ce.zip

Windows 32bits client zip: https://get.docker.com/builds/Windows/i386/docker-17.03.1-ce.zip

快速安装docker并启动

官方安装教程

新版的docker包名改为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 makecache fast
sudo yum install -y docker-ce
sudo systemctl enable docker
sudo systemctl start docker

清华大学镜像源提供docker安装镜像与说明

https://mirror.tuna.tsinghua.edu.cn/help/docker/

或者http://get.daocloud.io/docker/builds/查看

阿里云也提供安装脚本 见http://mirrors.aliyun.com/help/docker-engine,

阿里云的软件源可以使用内网源不占用外网流量

使用docker 需要开机宿主机IPV4转发功能,否则docker info 会有警告,容器内无法上网

sysctl -w net.ipv4.ip_forward=1

基本使用

运行docker -v即可查看当前docker版本 docker 分为两部分,一分部是docker daemon , 一部分是docker client

1.12.0及以后版本,采用dockerd启动daemon服务,之前版本采用docker daemon启动daemon服务.

docker daemon 与 client 可分离部署运行,如

docker daemon -H=unix:///var/run/docker.sock -H=0.0.0.0:4243 --default-ulimit nofile=1024:4096

服务器同时监听unixsocket和tcp端口,然后客户端设置远端服务变量export DOCKER_HOST=tcp://1.1.1.1:4243,就可以使用docker client,不过这种没有认证,适合局域网玩.

如果是在公网上,最好做一些身份认证

生成证书可参考官网 https://docs.docker.com/engine/security/https/

其他参考 https://github.com/chenzhiwei/linux/tree/master/ssl-cert

这里一份脚本可以快速生成证书,只需修改DOMAIN变量即可. https://gist.github.com/suconghou/707d9c61367c4bb91e8ed2585b094853

将证书放在~/.docker目录下可以免去设置DOCKER_CERT_PATH

放置生成的证书

sudo yum install -y zip curl
mkdir -pv ~/.docker && cp -vf ca.pem ~/.docker && mv server-cert.pem ~/.docker/cert.pem && mv server-key.pem ~/.docker/key.pem && zip -r client.zip ca.pem cert.pem key.pem && rm ca.pem cert.pem key.pem

docker service的配置vim /usr/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/cert.pem --tlskey=/root/.docker/key.pem -s devicemapper --storage-opt dm.datadev=/dev/centos/docker-data --storage-opt dm.metadatadev=/dev/centos/docker-metadata

最好是将这些配置写入/etc/docker/daemon.json 防止更新docker覆盖配置文件

{
    "registry-mirrors": [
        "https://docker.mirrors.ustc.edu.cn"
    ],
    "hosts": [
        "unix:///var/run/docker.sock",
        "tcp://0.0.0.0:2376"
    ],
    "storage-driver": "devicemapper",
    "storage-opts": [
        "dm.datadev=/dev/centos/docker-data",
        "dm.metadatadev=/dev/centos/docker-metadata"
    ],
    "tlsverify": true,
    "tlscacert": "/root/.docker/ca.pem",
    "tlscert": "/root/.docker/cert.pem",
    "tlskey": "/root/.docker/key.pem"
}

cat /etc/docker/daemon.json | python -m json.tool 格式化

sudo systemctl restart docker

client端配置下面这几个变量就好

export DOCKER_HOST=tcp://some.domain:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=$DIR

动态设置$DIR,将你的docker.env和证书放在相同文件夹下.

export DOCKER_HOST=tcp://some.domain:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=$(cd `dirname $0`; pwd)

可能防火墙iptanles或者firewalld拦截了其他端口,需要开放

systemctl stop firewalld

其他脚本参考

https://gist.github.com/bradrydzewski/a6090115b3fecfc25280

https://gist.github.com/cameron/10797040

搜索 docker search 镜像名字 下载 docker pull learn/tutorial, 下载时要写完整名字

若证书始终验证不通过可能是两者的时间不一致 ntpdate cn.pool.ntp.org 同步一下服务器时间.

改动后,重启docker服务生效.

sudo systemctl daemon-reload
sudo systemctl restart docker

官方Docker镜像一览

下载官方ubuntu docker pull ubuntu

运行此ubuntu docker run ubuntu echo "hello"

运行完以后docker容器就退出了.

进入此ubuntu的shell docker run -i -t ubuntu /bin/bash 也可以写为 docker run -it ubuntu /bin/bash

期间如果有需要退出按 Ctrl+P+Q,退出后,容器任然是运行的,Ctrl+D退出后容器停止

docker ps 查看正在运行的docker容器,可以看到后台的docker

重新进入容器需要docker attach CONTAINER 此命令代表Attach to a running container.

CONTAINER可以是最前面的CONTAINER ID ,也可以是最后面的NAMES

你还可以使用 docker run -it --name myname ubuntu /bin/bash 来指定它使用的名字,否则名字的随机的

你可以用不同的名字同时运行多个此种镜像

使用 docker rename hello hello2 将原先名字为hello的容器改名为hello2

使用 docker top hello2 查看运行在hello2中的所有进程

使用docker stats 查看容器运行的CPU,内存,网络等消耗统计

使用 docker pause hello2 将docker hello2 中的所有进程暂停,使用docker ps 可以看到容器已经暂停了

使用 docker unpass hello2 恢复暂停的容器

使用 docker stop hello2 将名字为hello2的容器停止

使用 docker ps -a 查看所有的容器,将会看到很多容器,因为每次执行docker run命令都是Run a command in a new container新建了一个容器, 可以考虑使用 docker start 容器名称 然后再docker attach 进去,你上次的改动依然在那.

也可以考虑使用docker rm 容器名称 删除容器以节约资源,rm后可用空格分隔多个容器名称,此命令执行较慢

也可以在创建的时候指明结束运行时清除docker容器docker run --rm ubuntu echo "hello"

或者将要执行的命令附加到正在运行的容器上docker exec hello2 echo "hihi"

docker start后立即退出,来不及attach时,使用docker start -ia vps 这种方式

使用docker rmi来删除镜像 docker ps 默认显示当前正在运行中的container docker ps -a 查看包括已经停止的所有容器 docker ps -l 显示最新启动的一个容器(包括已停止的)

使用docker info查看机器的配置,docker版本,容器和镜像的数量,存储驱动等

技巧: attach是可以带上--sig-proxy=false来确保CTRL-DCTRL-C不会关闭容器

这是一些经常使用的镜像相关的数据:

名称 描述 大小
scratch 基础镜像 大小为0
busybox 最小Unix系统 (uClibc) 1.1MB
Alpine 基于busybox(musl) 4.8MB
CirrOS 最小化的Linux发行版 7.7MB
ubuntu:16.04 Ubuntu 121MB
debian:jessie Debian最新版 125MB
centos:latest Centos最新版 196MB

文件系统

把一个宿主机上的目录挂载到镜像里

通过挂载的方式

通过-v参数,冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径.

docker run -it --name tmp -v /data/tmp:/home ubuntu /bin/bash

宿主目录不存在会自动创建,但是镜像内挂载路径必须存在,挂载后双向可写,实时生效 此镜像将一直保持挂载,stop,exit后重新进入,依然是挂载状态.

默认挂载的路径权限为读写.如果指定为只读可以用:ro docker run -it --name tmp -v /data/tmp:/home:ro ubuntu /bin/bash 挂载后,镜像内对挂载的数据不可写

docker还提供了一种高级的用法,叫数据卷. 数据卷:”其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的”.感觉像是由一个容器定义的一个数据挂载信息.其他的容器启动可以直接挂载数据卷容器中定义的挂载信息.

创建一个普通容器,定义一个名称,挂载目录. 数据容器是不需要运行的.

docker run -v /data/tmp:/home --name datafs busybox

其他容器使用这个数据卷 docker run -it --name tmp --volumes-from datafs ubuntu /bin/bash

--volumes-from 已过时,不建议使用.

通过volume方式(建议使用这种最新的方式)

docker1.9及以上可以使用docker volume create --name datafs创建volume 使用时类似docker run --name=yourcontainername -p 10022:22 -p 10080:3000 -v datafs:/data ubuntu

docker volume ls 查看创建的volume

docker volume rm用来删除

docker volume inspect datafs查看详情

这些数据是放在/var/lib/docker/volumes/下面的

docker的container是无状态的,也就是说标记状态的数据,例如:数据库数据,应用程序的log等等,是不应该放到container里的,而是放到 Data Volume Container里

建议使用Data Volume Container不要使用过去的方法了

网络系统

使用-p进行映射端口,第一个是外部端口,第二个是内部端口

默认的规则是TCP,如果需要UDP,采用类似-p 1234:1234/udp

-p 参数详解

http://udn.yyuap.com/doc/docker_practice/advanced_network/port_mapping.html

-p 80:8080容器内部的8080端口,对外暴漏于80端口 -p 22内部是22端口映射,外部则为一个随机可用的端口,-P则是将Dockerfile里EXPOSE的所有端口分配到宿主机的动态端口上,EXPOSE的端口不创建和宿主机的映射,是不能直接访问的

-p参数只能在docker run时指明,一旦生成了container就不能修改端口映射 可以采用如下方式生成新的容器修改

docker stop vps
docker commit vps vpsimage
docker rm vps
docker run -it -p 8080:8000 --name vps vpsimage bash

多个端口类似docker run -it --name vps -p 443:443 -p 80:8080 -p 8000:80 vpsimage bash

使用docker port vps可以查看此容器当前的端口映射,容器停止后,docker port vps不会显示出来,他显示的是正在工作的.

docker inspect vps 查看容器的详细配置信息,包括端口映射,来源镜像,日志存储路径,内存,CPU等

容器与镜像

容器: docker export docker import (不能用在镜像上)

镜像: docker save docker load (不能用在容器上)

在执行 导入以后,无论是import还是load,都会生成一个新的镜像.

导出后再导入exported-imported生成的镜像会丢失所有的历史.

而保存后再加载saveed-loaded生成的镜像没有丢失历史和层(layer).

这意味着使用导出后再导入的方式,你将无法回滚到之前的层(layer),

同时,使用保存后再加载的方式持久化整个镜像,就可以做到层回滚(可以执行docker tag <LAYER ID> <IMAGE NAME>来回滚之前的层)

docker history vpsimage 查看镜像的变迁历史

Export命令用于持久化容器[Export a container’s filesystem as a tar archive]

Save命令用于持久化镜像[Save an image(s) to a tar archive]

要转移一个正在使用中的容器,可以

接收方 nc -l 9090 | docker import - myimage

发送方 docker export container_name_or_id | nc 172.168.1.3 9090

容器

docker ps -a 查看所有的容器,包含已经停止的,暂停的,在运行的等,可以恢复运行,停止等,删除使用docker rm xx

修改容器名字:docker rename old new

导出:docker export vps > vpsdata.tar

导入:cat /home/vpsdata.tar | docker import – yourname,也可以通过指定 URL 或者某个目录来导入docker import http://example.com/exampleimage.tgz example/imagerepo

镜像

docker images 显示本机上存在的资源,大部分是docker pull下来的,可以使用 docker rmi xx 删除

修改镜像名字:docker tag old new 然后 docker rmi old

导出:docker save vpsimage > image.tar

导入:docker load < /home/image.tar

不使用重定向还可以使用参数

docker save -o image.tar vpsimage

docker load -i /home/image.tar

docker server 与 client 分离时,save,export等操作会非常慢,因为会通过网络把生成的文件下载到本地.

docker rm $(docker ps -q -a) 一次性删除所有的容器

docker rm $(docker ps -a -q) 删除所有停止运行的容器

docker rmi $(docker images -q) 一次性删除所有的镜像

docker ps -l -q 获取最后(-l)一个启动的容器id(-q)

docker rmi $(docker images | grep "^<none>" | awk "{print \$3}") 清除none标签的镜像

Docker 1.13 引进了新的管理命令,如下:

命令 docker system df 提供 Docker 整体磁盘使用率的概况,包括镜像、容器和(本地) volume

docker 提供命令可以直接查看容器的差异

提供 shell 用于分析两个 image的差异 https://github.com/moul/docker-diff

docker stats 显示容器名字

docker stats $(docker ps --format='{{.Names}}')

1.13 及以后可以

docker stats --format 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}'

国内加速

docker pull 默认采用https通信,国内一般提供镜像,或者自己的registry,可以采用 例如docker pull registry.aliyuncs.com/suconghou/http 这种方式指明registry

阿里云的registry,提供私有,公开docker镜像,单独https域名官方镜像加速

Daocloud提供的Docker服务地址 daocloud.io 并提供单独域名的加速器, 还有写好的脚本可以指定docker启动时使用的registry

网易提供的镜像 https://hub-mirror.c.163.com/

同时中科大USTC也提供镜像加速 https://docker.mirrors.ustc.edu.cn/https://servers.ustclug.org/2015/05/new-docker-hub-registry-mirror/

最新的配置帮助 https://lug.ustc.edu.cn/wiki/mirrors/help/docker

docker 配置文件 /etc/docker/daemon.json

配置镜像加速.

{
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}

配置文件介绍见 https://docs.docker.com/engine/reference/commandline/dockerd/

修改alpine linux 的镜像源地址

vi /etc/apk/repositories

http://dl-cdn.alpinelinux.org/alpine/v3.6/main
http://dl-cdn.alpinelinux.org/alpine/v3.6/community

可替换为

https://mirror.tuna.tsinghua.edu.cn/alpine/v3.6/main
https://mirror.tuna.tsinghua.edu.cn/alpine/v3.6/community

简化为

echo -e 'https://mirror.tuna.tsinghua.edu.cn/alpine/v3.6/main\nhttps://mirror.tuna.tsinghua.edu.cn/alpine/v3.6/community' > /etc/apk/repositories

使用流程

sudo groupadd docker

重新加载配置

sudo systemctl daemon-reload sudo systemctl restart docker

当你的docker不支持devicemapper存储驱动时,会报错 可以使用-s overlay 参数指定存储驱动

ExecStart=/usr/bin/docker daemon -s overlay -H fd://

如果已经启动docker daemon但是任然无法连接上,查看systemctl status docker.service 监听是否正确,如正确,查看当前登录的用户是否和docker用户一个组内 假设当前登录用户是root

sudo usermod -aG docker root
newgrp docker

再次重启docker daemon,退出当前用户再次登录

根据Dockerfile创建

sudo docker build -t="user/imgname:tag" .

其中-t标记来添加 tag,指定新的镜像的用户信息.

”.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径.

-f 指定dockerfile 的文件名称

如何使构建的镜像更小

  1. 基于busybox或者alpine等构建
  2. RUN 命令要尽量写在一条里,每次 RUN 命令都是在之前的镜像上封装,只会增大不会减小
  3. 新版本docker可以使用 多阶段构建(multi-stage build)

文件结构

进入目录查看 /var/lib/docker

volumes 目录里存放着创建的Data Volume Container

containers 目录存储启动的容器配置信息,查看docker ps -a里的CONTAINER ID和此文件夹下某些目录的前几位是相同的

graph pull的镜像信息保存在了graph文件夹下,镜像的内容存在了devicemapper/devicemapper/data 下,根据存储驱动不同,也可能存放在overlay目录,这些目录都比较大

ls -lh /var/lib/docker/graph/,进入一个文件夹,文件夹内保存着:

json -保存着关于这个镜像的元数据, cat json | python -m json.tool

layersize – 一个整数,表示layer的大小.

checksum - 一个sha256值

image

存储驱动

做paas一般使用aufs驱动,用于存储大量的docker,但是aufs只在ubuntu系的内核才自带此功能.

devicemapper驱动将所有文件存储在一个100G的虚拟磁盘,但是静态编译好的二进制文件不支持此驱动

overlay驱动将镜像里的各个文件还是存储在磁盘的各个文件,镜像过多存储的文件数量也很多,一般兼容性较好

aufs > overlay2 > devicemapper

docker 1.13 已将默认存储驱动由devicemapper修改为overlay了 有旧数据,新版docker不会自私切换驱动, 清除/var/lib/docker后重新启动,docker会使用新的驱动.

构建镜像

build images 使用 docker build -t="http" .

-t 指明tag 后面的.指明Dockerfile所在的目录

如果想要使用非Dockerfile为名字的构建文件可以使用-f参数指定构建文件

docker build -t=myimage -f mydockerfile .

还可以使用docker build -t=myimage - < mydockerfile , 不过尝试发现这种方式好像对路径处理有问题,还是推荐上面一种自定义的方式.

关联远端Docker Hub仓库

docker login 输入用户名,密码,邮箱登陆

docker push yourname/imagename

技巧

清除docker container log

使用 docker logs <container_name_or_id> 可以查看容器的log,也可以将重定向到一个文件,可以类似于tail -f一样跟踪变化.

但是未提供清空log的选项.

其实可以使用$(docker inspect --format='{{.LogPath}}' <container_name_or_id>)得出此容器的日志存储文件.

sudo ls -lh $(docker inspect --format='{{.LogPath}}' <container_name_or_id>) //查看日志文件
echo -n "" > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>) //可以清空日志文件

还可以使用truncate -s 0 /var/lib/docker/containers/*/*-json.log清空所有的日志文件.

不过这个都是需要docker daemondocker client在同一台机器上.

docker 1.8及以后版本可以使用参数--log-opt max-size=10m限制日志文件的大小,更多详细介绍 https://docs.docker.com/engine/admin/logging/overview/

使用docker -m可以限制内存的使用,这个是直到程序内存使用超过此限定的2倍,才会因OOM而被进程杀掉.容器仍会正常运行.

要使超过限定大小如100,就杀死,可以 -m 100m --memory-swap=100m

docker update 可以动态修改容器的资源限制

问题排查

systemctl status docker.service -l 可查看docker工作状态,为什么启动失败等

CoreOs使用docker

docker 配置远程访问.

sudo touch /run/flannel_docker_opts.env && sudo chmod 777 /run/flannel_docker_opts.env
sudo echo 'DOCKER_OPTS=" -H=unix:///var/run/docker.sock -H=0.0.0.0:4243  --registry-mirror=https://docker.mirrors.ustc.edu.cn"' > /run/flannel_docker_opts.env
sudo systemctl restart docker

semanage port -a -t http_port_t -p tcp 2376

解决 Usage of loopback devices is strongly discouraged for production use. Use–storage-opt dm.thinpooldevto specify a custom block storage device.

备份docker volume数据卷

文件接收端执行 nc -l 9090 > data.tar.gz 有些nc(busybox里的nc)可能是 nc -l -p 9090 > data.tar.gz

以只读模式挂载数据卷,挂载数据卷到/data路径

docker run --rm -it -v gogs-data:/data:ro busybox sh -c "cd /data && tar czvf - . | nc host 9090"

打包文件并发送到目标主机

恢复docker volume数据

如果没有这个数据卷,先创建数据卷 docker volume create --name gogs-data

docker run --rm -it -v gogs-data:/data busybox sh -c "nc -l -p 9090 | tar -C /data -zxf -"

然后通过宿主机发送数据 nc host 9090 < data.tar.gz

如果两台电脑可以直接连通

发送方 docker run --rm -it -v gogs-data:/data:ro busybox sh -c "cd /data && tar czvf - . | nc host 9090"

接收方 docker run --rm -p 9090:9090 -it -v gogs-data:/data busybox sh -c "nc -l -p 9090 | tar -C /data -zxf -"

参考 https://blog.lab99.org/post/docker-2016-07-14-faq.html#docker-yin-qing-xiang-guan-wen-ti-61

docker service ls docker node ls docker stack ls docker swarm

音乐标题
歌手