docker 使用笔记

"docker notes"

Posted by leiyiming on April 24, 2018

docker 常用命令


docker run --name <name> -it <image> /bin/bash 启动容器

docker start/stop/restart <container> 开启/停止/重启容器

docker exec -it <name/ID> bin/bash 进入容器

ctrl p + q 退出不关闭容器

docker ps 查看正在运行的容器

docker ps -a 查看所有的容器,包括已经停止的。

docker rm $(docker ps -a -q) 删除所有容器

docker run -it -v /home/dock/Downloads:/usr/Downloads ubuntu64 /bin/bash 挂载目录,冒号前为宿主机目录,必须是绝对路径

docker cp <containerId>:/file/path/within/container /host/path/target 从docker拷贝数据到宿主机

docker inspect container_name | grep Mounts -A 20 查看容器挂载目录

docker run [OPTIONS] IMAGE COMMAND    

-d, --detach=false         指定容器运行于前台还是后台,默认为false     

-i, --interactive=false   打开STDIN,用于控制台交互    

-t, --tty=false            分配tty设备,该可以支持终端登录,默认为false    

-u, --user=""              指定容器的用户    

-a, --attach=[]            登录容器(必须是以docker run -d启动的容器)  

-w, --workdir=""           指定容器的工作目录   

-c, --cpu-shares=0        设置容器CPU权重,在CPU共享场景使用    

-e, --env=[]               指定环境变量,容器中可以使用该环境变量    

-m, --memory=""            指定容器的内存上限    

-P, --publish-all=false    指定容器暴露的端口    

-p, --publish=[]           指定容器暴露的端口,3306:3306,映射本机的3306端口到虚拟机的3306端口。

-h, --hostname=""          指定容器的主机名    

-v, --volume=[]            给容器挂载存储卷,挂载到容器的某个目录    

--volumes-from=[]          给容器挂载其他容器上的卷,挂载到容器的某个目录  

--cap-add=[]               添加权限,权限清单详见:http://linux.die.net/man/7/capabilities    

--cap-drop=[]              删除权限,权限清单详见:http://linux.die.net/man/7/capabilities    

--cidfile=""               运行容器后,在指定文件中写入容器PID值,一种典型的监控系统用法    

--cpuset=""                设置容器可以使用哪些CPU,此参数可以用来容器独占CPU    

--device=[]                添加主机设备给容器,相当于设备直通    

--dns=[]                   指定容器的dns服务器    

--dns-search=[]            指定容器的dns搜索域名,写入到容器的/etc/resolv.conf文件    

--entrypoint=""            覆盖image的入口点    

--env-file=[]              指定环境变量文件,文件格式为每行一个环境变量    

--expose=[]                指定容器暴露的端口,即修改镜像的暴露端口  

--link=[]                  指定容器间的关联,使用其他容器的IP、env等信息 

--lxc-conf=[]              指定容器的配置文件,只有在指定--exec-driver=lxc时使用 

--name=""                  指定容器名字,后续可以通过名字进行容器管理,links特性需要使用名字 

--net="bridge"             容器网络设置: 

Dockerfile


FROM

指定基础镜像,并且必须是第一条指令。

如果不以任何镜像为基础,那么写法为:FROM scratch。同时意味着接下来所写的指令将作为镜像的第一层开始。

语法:

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest> 

三种写法,其中 是可选项,如果没有选择,那么默认值为 latest。

MAINTAINER

指定作者

语法:

MAINTAINER <name> "email"

RUN

运行指定的命令,RUN命令有两种格式:

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

第一种后边直接跟shell命令。

  • 在linux操作系统上默认 /bin/sh -c
  • 在windows操作系统上默认 cmd /S /C

第二种是类似于函数调用。可将 executable 理解成为可执行文件,后面就是两个参数。

两种写法比对:

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
RUN ["/bin/bash", "-c", "echo hello"]

注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层,多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。

CMD

容器启动时要运行的命令,语法有三种写法:

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

第三种比较好理解,和shell执行方式一样,第一种和第二种其实都是可执行文件加上参数的形式。举例说明两种写法:

CMD [ "sh", "-c", "echo $HOME" 
CMD [ "echo", "$HOME" ]

补充细节:这里边包括参数的一定要用双引号,不能是单引号。因为参数传递后,docker解析的是一个JSON array。

RUN & CMD 区别

  • RUN 的功能是构建容器时运行命令并提交运行结果。
  • CMD 是容器启动时执行的命令!在构建时并不运行,构建时仅仅指定了容器的启动命令。如果没有指定 HEALTHCHECK ,在运行时,Docker 的生死状态依赖于 CMD 指定的命令的生死状态!也就是说,如果 CMD 指定的命令挂掉了,相应的,Docker 也会挂掉!

LABEL

为镜像指定标签,语法:

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

一个 Dockerfile 中可以有多个 LABEL ,如下:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

说明:LABEL 会继承基础镜像中的 LABEL,如遇到 key 相同,则值覆盖。

EXPOSE

暴露容器运行时的监听端口给外部,但是 EXPOSE 并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P 参数。

EXPOSE 12345

ENV

功能为设置环境变量

语法有两种

1. ENV <key> <value>
2. ENV <key>=<value> ...

两者的区别就是第一种是一次设置一个,第二种是一次设置多个。

ADD

一个复制命令,把文件复制到景象中。

如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用。语法如下:

ADD <src>... <dest>
ADD ["<src>",... "<dest>"]

dest 路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径。

src 可以是一个本地文件或者是一个本地压缩文件,还可以是一个 url。如果把 src 写成一个url,那么 ADD 就类似于 wget 命令

如以下写法都是可以的:

ADD test relativeDir/ 
ADD test /relativeDir
ADD http://example.com/foobar /

COPY

另一个复制命令。语法如下:

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]

与ADD的区别:COPY的 src 只能是本地文件,其他用法一致。

ENTRYPOINT

容器启动时,默认执行的命令。语法如下:

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

ENTRYPOINT 与 CMD 的区别

  1. 相同点:
  • 只能写一条,如果写了多条,那么只有最后一条生效。
  • 容器启动时才运行,运行时机相同。
  1. 不同点:
  • ENTRYPOINT 不会被运行的 command 覆盖,而 CMD 则会被覆盖。
  • 如果我们在 Dockerfile 中同时写了 ENTRYPOINTCMD ,那么 CMD 指定的内容将会作为 ENTRYPOINT 的参数。

(留坑,区别没有理解清楚)

VOLUME

实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器中,语法为:

VOLUME ["/data"]

说明:

["/data"] 可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的:

VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db

一般的使用场景为需要持久化存储数据时,容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失,所以当数据需要持久化时用这个命令。

USER

设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的

USER daemo
USER UID

注意:如果设置了容器以 daemon 用户去运行,那么 RUNCMDENTRYPOINT 都会以这个用户去运行。

WORKDIR

设置工作目录,语法:

WORKDIR /path/to/workdir

RUNCMDENTRYPOINTCOPYADD 生效。如果不存在则会创建,可以设置多次。如:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

pwd 执行的结果是 /a/b/c

WORKDIR也可以解析环境变量,如:

ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

pwd 的执行结果是 /path/$DIRNAME

ARG

设置变量命令,语法:

ARG <name>[=<default value>]

ARG 命令定义了一个变量,在 docker build 创建镜像的时候,使用 –build-arg = 来指定参数。

HEALTHCHECK

容器健康状况检查命令

语法有两种:

HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE

第一个的功能是在容器内部运行一个命令来检查容器的健康状况。

第二个的功能是在基础镜像中取消健康检查命令。

[OPTIONS] 的选项支持以下三种:

  • --interval=DURATION 两次检查默认的时间间隔为30秒。
  • --timeout=DURATION 健康检查命令运行超时时长,默认30秒。
  • --retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3。

注意:HEALTHCHECK 命令只能出现一次,如果出现了多次,只有最后一个生效。

CMD 后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:

  • 0: success - 表示容器是健康的
  • 1: unhealthy - 表示容器已经不能工作了
  • 2: reserved - 保留值

例子:

HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1

健康检查命令是:curl -f http://localhost/ || exit 1 两次检查的间隔时间是5秒,命令超时时间为3秒

docker compose


docker-compose logs -f xxx 查看docker日志

docker-compose up -d 创建并启动docker-compose

docker-compose down 关闭并删除docker-compose

docker-compose start 启动docker-compose

docker-compose stop 关闭docker-compose

docker-compose restart 重启docker-compose

docker-compose build 构建docker-compose

docker-compose.yml


devices

设置设备映射。

depends_on

指定 Compose 中Docker 的依赖顺序,启动时会根据依赖关系先后启动Docker。

    depends_on:
      - db

environment

添加环境变量。

    environment:
      - ENV=dev

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

链接到 docker-compose.yml 之外声明管理的容器。

extra_hosts

添加主机名,往 /etc/hosts 文件中添加记录。

image

从指定的镜像启动容器。

image: centos:latest

连接到 docker-compose.yml 中声明管理的容器。

aliases

设置 Docker 的别名,同一网络上的其他容器可以使用别名来连接该容器。

ports

端口映射。

ports:
      - "9898:9898"

volumes

挂载目录。

cpus

只能在2.2版本以上使用

限制容器最大使用的宿主机CPU比例。比如值为2,则最大只能使用200%的CPU,注意并不是只能用2个核,而是各个核使用率之和不会超过200%

cpus: 2

mem_limit

限制容器最大使用的宿主机内存。

mem_limit: 4096m

例子

version: "3"
services:

  redis:
    image: redis:alpine
    ports:
      - "6379"
    networks:
      - frontend
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

  db:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints: [node.role == manager]

  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - "5000:80"
    networks:
      - frontend
    depends_on:
      - redis
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure

  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - "5001:80"
    networks:
      - backend
    depends_on:
      - db
    deploy:
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend
      - backend
    deploy:
      mode: replicated
      replicas: 1
      labels: [APP=VOTING]
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
        window: 120s
      placement:
        constraints: [node.role == manager]

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]

networks:
  frontend:
  backend:

volumes:
  db-data: