Docker
Contents
[NOTE] Updated April 5, 2018. This article may have outdated content or subject matter.
Docker
Docker是一个容器引擎, 分为社区版CE, 和企业版EE, Docker不是虚拟机, 也不依赖虚拟化技术.
docker-cli -> dockerd -> containerd -> docker-shim -> runc
Docker包括三个基本概念:
- 仓库repository,集中存放镜像文件的场所,docker hub/store是最大的公开仓库.
- 镜像image, 镜像是一个文件系统.
- 容器container, 容器是镜像的运行的实例.
修改默认register:
1 2 3 4 5 6 7 |
# https://z4yd270h.mirror.aliyuncs.com # http://f1361db2.m.daocloud.io # https://docker.mirrors.ustc.edu.cn $ sudo vim /etc/docker/daemon.json { "registry-mirrors": ["https://registry.docker-cn.com"] } |
禁止docker修改iptables:
1 2 |
$ sudo vim /lib/systemd/system/docker.service > ExecStart=/usr/bin/dockerd -H fd:// --iptables=false |
修改docker存储路径:
1 2 3 4 |
$ service docker stop $ mv /var/lib/docker /opt/ssd/docker $ ln -s /opt/ssd/docker /var/lib/docker $ service docker start |
Install:
1 2 3 4 5 |
windows: <https://docs.docker.com/docker-for-windows/install/> linux: <https://docs.docker.com/install/linux/docker-ce/> |
docker命令
image管理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ docker image COMMAND > 查看本地镜像: $ docker image ls $ docker image -a > 根据创建dockerfile,创建新的images $ docker image build > 创建tag $ docker image tag > 删除image $ docker image rm <IMAGE ID> $ docker rmi <IMAGE ID> > 删除所有image $ docker rmi $(docker images -a -q) > 清理所有临时images $ docker image prune |
container管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
$docker container COMMAND # 列出container: $ docker container ls $ docker ps -a # 默认只显示running状态的 # 运行image,产生一个container: $ docker container run <IMAGE ID>/<REPOSITORY> [COMMAND] [ARGS] # 在container中执行命令 $ docker container exec [OPTIONS] <CONTAINER> COMMAND [ARG...] # 创建container但不启动 $ docker container create --name <name> <CONTAINER> # 启动container: $ docker container start/restart <CONTAINER> # 停止container: $ docker container stop <CONTAINER> # 删除container: $ docker container rm <CONTAINER> $ docker rm <CONTAINER> # 删除所有容器 $ docker rm $(docker ps -a -q) # 清理停止的container $ docker container prune |
制作镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# 根据Dockerfile 构建image docker build [OPTIONS] PATH | URL | - docker build . // 默认就是当前目录的Dockerfile docker build -t <repo>/<name>:<tag> . // 创建tag docker build -f /path/to/mydockerfile . // 也可以指定其它路径的其它文件 docker build --target <stage> . // 指定阶段构建. docker build ... --network=host // 使用host网络构建. docker build --no-cache // 不使用缓存数据 # 把image导出到tar包 # 既可以从image也可以从container导出。 # 从container导出不包含运行后的修改,只导出原始镜像。 $ docker save -o name.tgz <repo1>:<tag1> <repo2>:<tag2> ... # 从stdin或文件加载image docker load [OPTIONS] docker load < name.tar.gz docker load --input/-i name.tar # 把container导出到tar包,从container导出镜像。 # 包括container启动后的修改。 docker export -o name.tar [container] # 从container导出的包加载成镜像 docker import name.tar [repo]:[tag] # 根据container的修改创建新的image docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] docker commit -a "author" -c "Dockerfile instruction" -m "commit message" CONTAINER [REPOSITORY[:TAG]] # 创建新的tag docker tag <old> <new> |
运行容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# 创建一个新的container并运行命令 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] docker run --name [NAME] IMAGE // 运行容器并命名 docker run -d IMAGE // 后台运行 docker run -it IMAGE /bin/bash // 交互模式启动容器 docker run -P IMAGE // 默认将容器的80端口映射到主机的随机端口 docker run -p [host:port]:[containerPort] // 指定映射端口 --add-host # 相当于修改容器的/etc/hosts,但是容器重启后不会消失 -h/--hostname # 修改容器的/etc/hostname --cpus decimal Number of CPUs -c, --cpu-shares int CPU shares (relative weight) --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) --cpu-period --cpu-quota -m, --memory bytes Memory limit --memory-reservation bytes Memory soft limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1) --oom-kill-disable --oom-score-adj --kernel-memory # 在运行的container中执行命令 docker exec [OPTIONS] CONTAINER COMMAND [ARG...] docker exec -d CONTAINER ... // 在后台运行 docker exec -it CONTAINER /bin/bash ... // 进入命令行 |
其它命令
1 2 3 4 5 6 7 8 |
# 在container和host之前拷贝文件和目录 docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH # 查看容器的日志 docker logs [OPTIONS] CONTAINER docker diff CONTAINER docker history [OPTIONS] IMAGE |
register使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 登陆到docker hub 或其他register docker login docker login -u/--username <user> -p/--password <password> # 从docker hub/store查找images $ docker search [OPTIONS] TERM $ docker search # 从registry获取repository/images到/var/lib/docker: $ docker pull [OPTIONS] NAME[:TAG|@DIGEST] $ docker pull $ docker pull ubuntu # 默认下载所有tag $ docker pull ubuntu:14.04 # 从中国站点下载 $ docker pull registry.docker-cn.com/library/ubuntu:16.04 # 推送到docker hub $ docker push |
Dockerfile
ADD
1 2 3 |
# add可以是远程文件,不推荐使用 ADD [--chown=<user>:<group>] <src>... <dest> ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] |
COPY
1 2 3 |
# 只能操作本地文件 COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] |
ENV
1 2 3 |
# 指定容器中的环境变量 ENV <key> <value> ENV <key>=<value> ... |
EXPOSE
1 2 |
# 指定容器需要映射到主机的端口 EXPOSE <port> [<port>/<protocol>...] |
FROM
1 2 3 |
FROM <image> [AS <name>] FROM <image>[:<tag>] [AS <name>] FROM <image>[@<digest>] [AS <name>] |
LABEL
1
|
LABEL <key>=<value> <key>=<value> <key>=<value> ... |
STOPSIGNAL
1
|
STOPSIGNAL signal |
USER
1 2 |
USER <user>[:<group>] USER <UID>[:<GID>] |
VOLUME
1 2 |
# 指定挂载点做数据持久化 VOLUME ["/data"] |
WORKDIR
1 2 |
# 对run/cmd/entrypoint有效的工作目录 WORKDIR /path/to/workdir |
RUN
1 2 3 |
# 在容器构建过程中运行 RUN <command> # shell 格式 RUN ["executable", "param1", "param2"] # exec 格式 |
CMD
1 2 3 4 5 |
# 在容器运行过程中运行, 可以被覆盖 CMD ["executable", "param1", "param2"] # exec格式 CMD command param1 param2 # shell 格式 // 同时有cmd和entrypoint,cmd只是entrypoint的参数. CMD ["param2", "param2"] # entrypoint的参数 |
ENTRYPOINT
1 2 3 |
# 和cmd类似,指定容器运行过程中的执行命令 ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred) ENTRYPOINT command param1 param2 |
ARG
1
|
ARG <name>[=<default value>] |
ONBUILD
1
|
ONBUILD ... |
stage:
1 2 |
COPY --from=stage1 / . docker build --target stage1 -t docker:latest . |
docker-compose
https://github.com/docker/compose
通过一个yaml文件来管理容器中的服务,包括网络和存储。
安装:
1 2 3 |
https://docs.docker.com/compose/install/ $ sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose |
docker-compose命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...] -f/--file -p/--project-name # 默认目录名 -H/--host # 拉取compose文件中指定的镜像 $ docker-compose -f service.yml pull # 根据docker-compose.yml把stack打包成一个Distributed Application Bundles文件. $ docker-compose bundle -o <project name>.dab $ docker-compose start [servoce...] $ docker-compose stop [service...] $ docker-compose restart [service...] $ docker-compose up -d [service...] $ docker-compose down -v $ docker-compose logs -f |
docker-compose.yml
compose文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
version: "3.6" services: mongo: image: mongo:latest hostname: hostname deploy: // for swarm networks: - mynetwork volumes: // short syntax - myvolume:/container/dir volumes: // long syntax - type: valume/bind/tmpfs source: target: read_only: bind: volume: tmpfs: consistency: ports: // long syntax - target: 80 published: 8080 mode: host protocol: tcp/udp ports: // short syntax - 80:80 - 1234:1234/udp environment: RABBITMQ_DEFAULT_USER: sandbox RABBITMQ_DEFAULT_PASS: password environment: - RABBITMQ_DEFAULT_USER=sandbox - RABBITMQ_DEFAULT_PASS=password depends_on: - service-name command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"] # 下列选项不能用于swarm stack部署. build cgroup_parent container_name devices tmpfs external_links links network_mode restart security_opt sysctls userns_mode // 使用已经创建好的网络 networks: mynetwork: external: name: lan0 // 创建bridge网络 networks: mynetwork: driver: bridge driver_opts: com.docker.network.bridge.name: lan0 ipam: driver: default config: - subnet: 192.168.1.0/24 // 创建overlay网络 networks: ol0: driver: overlay attachable: true driver_opts: com.docker.network.bridge.name: ol0 ipam: driver: default config: - subnet: 172.12.0.0/16 // 解析为: "line1 line2\n", 会自动加换行符. command: > line1 line2 // 解析为: "line1 line2", 没有换行符. command: >- line1 line2 # compose文件中用到的变量 .Service.ID Service ID .Service.Name Service name .Service.Labels Service labels .Node.ID Node ID .Node.Hostname Node Hostname .Task.ID Task ID .Task.Name Task name .Task.Slot Task slot |
docker-machine
https://github.com/docker/machine
在本地安装docker和docker-machine,然后就可以从本机安装或管理远程机器上的docker.
需要添加ssh的无密码登陆:
1
|
ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote-ip |
安装:
1 2 3 |
https://docs.docker.com/machine/install-machine/$ base=https://github.com/docker/machine/releases/download/v0.16.0 && curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine && sudo install /tmp/docker-machine /usr/local/bin/docker-machine |
docker-machine命令
1 2 3 4 5 6 |
docker-machine create -d generic \ --generic-ip-address=remote-ip \ --generic-ssh-user=user \ --generic-ssh-key ~/.ssh/id_rsa \ node1 docker-machine ls |
OOM
https://docs.docker.com/config/containers/resource_constraints/
https://github.com/docker/compose/issues/4513
swarm mode:
swarm模式使用compose format 3来限制资源.
https://docs.docker.com/compose/compose-file/#resources
non swarm mode:
非swarm模式可以用compose format 2 来做资源限制.
https://docs.docker.com/compose/compose-file/compose-file-v2/#cpu-and-other-resources
Author Canux
LastMod 2018-04-05