Docker

Docker基础

  1. 官方文档

    1
    https://docs.docker.com/
  2. Docker安装:

    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
    安装前检查
    1.内核版本
    uname -a
    2.检查Device Mapper
    ls -l /sys/class/misc/device-mapper
    Ubuntu中安装Docker的方式
    1.安装Ubuntu维护的版本(版本相对官方有可能会低点)
    安装: sudo apt-get install docker.io
    更新配置: source /etc/bash_completion.d/docker.io
    2.安装Docker维护的版本(推荐)
    wget -qO- https://get.docker.com/ | sh
    输入当前用户的密码后,就会下载脚本并且安装Docker及依赖包。
    安装完成后有个提示:
    If you would like to use Docker as a non-root user, you should now consider
    adding your user to the "docker" group with something like:
    sudo usermod -aG docker runoob
    Remember that you will have to log out and back in for this to take effect!

    意思是:当要以非root用户可以直接运行docker时,需要执行 sudo usermod -aG docker [user] 命令,然后重新登陆,否则会有如下报错

    可以通过直接输入docker命令查看Docker客户端的所有命令选项
    可以通过命令 docker command --help 更深入的了解指定的 Docker 命令使用方法。
    例如我们要查看 docker stats 指令的具体使用方法:
    docker stats --help
    3.测试
    sudo docker run hello-world
    4.非root用户运行docker
    创建一个用户组: sudo groupadd docker
    将当前用户添加到用户组: sudo gpasswd -a ${USER} docker
    注销并重新启动docker服务: sudo service docker restart
  3. 镜像的基本操作

    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
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    1. 查看版本
    docker version

    2. 查看docker信息
    docker info

    3. 列出镜像
    docker images [OPTSIONS] [REPOSITORY]
    -a --all=false 显示所有镜像,包括中间层镜像
    -f --filter=[] 显示时的过滤条件
    --no-trunc=false 不截断镜像的唯一id
    -q --quiet=false 只显示镜像的唯一id

    4. 查看镜像
    docker inspect [OPTSIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]

    5. 删除镜像
    docker rmi [OPTIONS] IMAGE [IMAGE...]
    -f --force=false 强制删除镜像
    --no-prune=false 保留未打标签的父镜像

    6. 查找镜像
    方式一:Docker Hub
    https://registry.hub.docker.com

    方式二:
    docker search [OPTIONS]
    --automated=false 只显示自动化构建的镜像
    --no-trunc=false 不截断显示
    -s --stars=0 过滤分数需要高于设置的镜像

    7. 拉取镜像
    docker pull [OPTIONS] NAME[:TAG]
    -a --all-tags=false 匹配名字的镜像全部下载到本地

    修改镜像获取地址
    使用--registry-mirror选项
    1.修改:/etc/default/docker
    2.添加:DOCKER_OPTS="--registry-mirror=http://MIRROR-ADDR"
    https://www.daocloud.io

    8. 推送镜像
    docker push NAME[:TAG]

    9. 查看镜像构建过程
    docker history IMAGE

    10. 构建镜像
    使用commit构建镜像
    docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    -a --author="" 指定作者
    -m --message="" 指定信息
    -p --pause=true 不暂停容器并提交

    使用Dockerfile构建镜像
    1. 创建Dockerfile文件
    #First Dockerfile
    FROM ubuntu:14.04 # 源仓库
    MAINTAINER 维护人 "维护人邮箱"
    RUN command1 # 执行的命令
    RUN command2 # 执行的命令
    RUN command3 # 执行的命令
    ...
    EXPOSE 80 # 暴露的端口
    CMD command4
    2. 使用docker build 命令
    docker build [OPTIONS] PATH|URL|-
    --force-rm=false
    --no-cache=false 不启用构建缓存
    --pull=false
    -q --quiet=false 静默操作,不打印日志
    --rm=true
    -t --tag="" 指定仓库名字
    3. Dockerfile指令
    1. 注释
    以#开头,单行注释

    2. 指令
    以大写的指令名开始,后面接着指令参数

    3. FROM指令:指定基础镜像
    格式:
    FROM <image>
    FROM <image>:<tag>
    要求:
    已经存在的镜像
    必须是第一条非注释指令

    4. MAINTAINER指令:指定镜像作者信息,包含镜像所有者和联系信息,相当于commit命令的-a属性
    格式:
    MAINTAINER <name>

    5. RUN指令:指定当前镜像中运行的命令,每条RUN指令都会基于上一条RUN指令的新镜像上添加
    格式:
    RUN <command> (shell模式)
    例:/bin/sh -c command 相对于执行了该命令
    RUN echo hello
    RUN ["executable","param1","param2"] (exec模式)
    例:RUN ["/bin/bash","-c","echo hello"]

    6. EXPOSE指令:指定运行该镜像的容器使用的端口
    格式:
    EXPOSE <port> [<port>...] 可以指定一个或多个端口,也可使用多个EXPOSE命令
    注意:
    虽然在构建镜像指定了端口,在容器运行时也需要通过run -p参数指定所使用的端口

    7. CMD指令:提供容器运行时默认命令,于RUN指令相似,但是RUN指令是在镜像构建过程中执行的,CMD指令是在容器运行时运行的
    格式:
    CMD <command> (shell模式)
    CMD ["executable","param1","param2"] (exec模式)
    CMD ["param1","param2"] (作为ENTRYPOINT指令的默认参数)
    注意:
    如果docker run指定了运行时的命令,那么CMD命令会被覆盖,也就是说CMD命令指定的时默认命令

    8. ENTRYPOINT指令:与CMD指令相似,区别在于命令不会被覆盖,run指定的命令并不会执行
    格式:
    ENTRYPOINT ["executable","param1","param2"] (exec模式)
    ENTRYPOINT <command> (shell模式)
    注意:
    如果需要覆盖,可以使用docker run --entrypoint覆盖
    高级用法:
    用ENTRYPOINT来指定命令,用CMD来指定命令默认参数
    ENTRYPOINT ["/vsr/bin/nginx"]
    CMD ["-h"]

    9. ADD指令和COPY指令:将本地文件或目录复制到镜像中
    格式:
    ADD <src>...<dest>
    ADD ["<src>"..."<dest>"](适用于文件路径中有空格的情况)
    COPY <src>...<dest>
    COPY ["<src>"..."<dest>"](适用于文件路径中有空格的情况)
    src:可以是本地地址(必须是构建目录中的相对地址)和远程URL(不推荐)
    dest:镜像中的绝对路径
    区别:
    ADD vs COPY
    ADD 包含类似tar的解压功能
    如果单纯复制文件,Docker推荐使用COPY

    10. VOLUME指令:向镜像容器添加卷,生成成数据卷容器
    格式:
    VOLUME ["/data"]
    注意:
    该操作不能指定主机目录,由容器运行时动态生成主机挂载的目录

    11. WORKDIR指令:在容器内部指定工作目录
    格式:
    WORKDIR /path/to/workdir CMD和ENTRYPOINT都会在这个目录下执行

    12. ENV指令:设置容器环境变量
    格式:
    ENV <key> <value>
    ENV <key>=<value>...

    13. USER指令:指定镜像会以什么样的用户去运行
    格式:
    USER daemon 可以使用uid:gid:group
    USER user USER uid
    USER user:group USER uid:gid
    USER user:gid USER uid:group

    14. ONBUILD [INSTRUCTION]:为镜像添加触发器,当一个镜像被其他镜像作为基础镜像时执行,会在构建过程中插入指令
    格式:
    ONBUILD [INSTRUCTION]
    例:
    ONBUILD COPY <src> <dest>
  4. 镜像的导入导出

    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
    1. 镜像导出
    docker save [OPTIONS] IMAGE [IMAGE...]
    -o --output string 输出到文件
    例:
    docker save -o nginx.tar nginx:latest

    docker save > nginx.tar nginx:latest
    其中-o和>表示输出到文件,nginx.tar为目标文件,nginx:latest是源镜像名(name:tag)

    2. 镜像导入
    docker load [OPTIONS]
    -i --input 从文件输入
    例:
    docker load -i nginx.tar

    docker load < nginx.tar
    其中-i和<表示从文件输入。会成功导入镜像及相关元数据,包括tag信息

    3. 容器导出
    docker export [options] container
    -o --output string 输出到文件
    例:
    docker export -o nginx-test.tar nginx-test
    其中-o表示输出到文件,nginx-test.tar为目标文件,nginx-test是源容器名(name)

    4. 容器导入
    docker import [options] file|URL|- [REPOSITORY[:TAG]]
    例:
    docker import nginx-test.tar nginx:imp

    cat nginx-test.tar | docker import - nginx:imp

    5. 说明与需要注意的地方
    1. export命令导出的tar文件略小于save命令导出的
    2. export命令是从容器(container)中导出tar文件,而save命令则是从镜像(images)中导出
    3. 基于第二点,export导出的文件再import回去时,无法保留镜像所有历史(即每一层layer信息,不熟悉的可以去看Dockerfil),不能进行回滚操作;而save是依据镜像来的,所以导入时可以完整保留下每一层layer信息。如下图所示,nginx:latest是save导出load导入的,nginx:imp是export导出import导入的

    6. 建议
    若是只想备份images,使用save、load即可
    若是在启动容器后,容器内容有变化,需要备份,则使用export、import
  5. 容器的基本操作

    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
    1. 启动容器
    docker run IMAGE [COMMAND] [ARG...]
    run 在新容器中执行命令

    2. 启动交互式容器
    docker run [--name 自定义名字] -i -t IMAGE /bin/bash
    -i --interactive=true | false 默认是false 告诉docker父进程始终打开标准输入
    -t --tty=true | false 默认是false 告诉docker父容器提供一个tty终端

    将交互式容器派遣为守护石形式运行的容器
    Ctrl+P Ctrl+Q

    3. 附加到运行中的容器
    docker attach [CONTAINER ID或NAME]

    4. 直接启动守护式容器
    docker run -d IMAGE [COMMAND] [ARG...]
    -d --detach 派遣为守护式容器启动

    5. 查看容器日志
    docker logs [-f] [-t] [--tail SIZE] [CONTAINER ID或NAME]
    -f --follows=true | false 默认式false 一直跟踪日志变化并打印出来
    -t --timestamps=true | false 默认式false 在日志列加上时间戳
    --tail=数量 返回结尾处多少数量的日志,0则默认最新

    6. 查看容器内进程
    docker top [CONTAINER ID或NAME]

    7. 在运行中的容器内启动新进程
    docker exec [-d] [-i] [-t] [CONTAINER ID或NAME] [COMMAND] [ARG...]

    8. 查看创建了那些容器
    docker ps [-a] [-l]
    -a 显示所有容器,包括已经停止的
    -l 显示 最新的容器
    -q 只显示容器id

    查看容器信息
    docker inspect [CONTAINER ID或NAME]

    高级用法:
    停止所有容器:docker stop $(docker ps -a -q)
    移除所有容器:docker rm $(docker ps -a -q)

    9. 重新启动已经停止的容器
    docker start -i [CONTAINER ID或 NAME]

    10. 停止正在运行的容器
    docker stop [CONTAINER ID或NAMES]
    docker kill [CONTAINER ID或NAMES] 强制停止容器

    11. 删除不需要的容器,删除容器时,容器必须是停止状态,否则会报异常
    docker rm [-v] [CONTAINER ID或NAME]
    -v 删除挂载的数据卷
    12. 查看端口映射
    docker port [CONTAINER ID或NAMES]

    13. 设置容器端口映射
    run [-P] [-p]
    -P --publish-all=true | false 默认式false
    docker run -P -i -t ubuntu /bin/bash 将容器内部使用的端口映射到主机上
    -p --publish=[]
    containerPort
    docker run -p 80 -i -t ubuntu /bin/bash 将容器80端口随机映射到主机上
    hostPort:containerPort
    docker run -p 8080:80 -i -t ubuntu /bin/bash 将容器80端口映射到主机8080端口上
    ip::containerPort
    docker run -p 0.0.0.0:80 -i -t ubuntu /bin/bash 将容器80端口映射到主机0.0.0.0上
    ip:hostPort:containerPort
    docker run -p 0.0.0.0:8080:80 -i -t ubuntu /bin/bash 将容器80端口映射到主机0.0.0.0:8080上

    14. 设置容器的数据卷
    run [-v]
    -v --volume 设置容器数据卷[主机目录:容器目录(绝对路径)],如果主机目录不存在会自动新建
    设置卷只读权限
    docker run -v 主机目录:容器目录:ro IMAGE [COMMAND] [ARG...]
    设置读写权限
    docker run -v 主机目录:容器目录:rw IMAGE [COMMAND] [ARG...]
  6. Docker的C/S模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    1. Remote API调用
    https://docs.docker.com/develop/sdk/examples/

    2. 连接模式
    模式一: unix:///var/run/docker.sock
    例:
    本地sock地址 /var/run/docker.sock
    curl --unix-socket /var/run/docker.sock http:/v1.24/images/json
    模式二: tcp://host:port 端口port通常为2375
    模式三: fd://socketfd
  7. Docker的远程访问

    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
    1. 要求Docker server和Dokcer client版本一致

    2. 修改Docker守护进程启动选项
    -H tcp://host:port
    unix:///path/to/socket
    fd://* or fd://socketfd
    -H指定Docker的通讯方式
    守护进程默认配置
    -H unix:///var/run/docker.sock

    3. 远程连接
    假设服务器A地址为:10.211.55.5
    服务器A Docker启动配置:-H tcp://0.0.0.0:2375

    服务器B请求远程api:curl 10.211.55.5:2375 http:/v1.24/images/json

    4. 使用本地Docker client操作远程Docker server
    服务器B
    方式一:
    本地Docker启动选项:-H tcp://10.211.55.5:2375 ip地址为远程服务器地址
    方式二:
    使用Docker环境变量配置调用远程Docker server: export DOCKER_HOST="tcp://10.211.55.5:2375"
    配置完成后就可以像使用本机Docker一样使用远程服务

    5. docker配置远程服务后本地服务不能正常调用
    即服务器A设置为远程服务后,相关的docker命令无法调用,如:docker info 会返回异常
    如果想要开发远程服务同时运行本地服务,可同时调用多次-H配置
    服务器A Docker启动配置:-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

  8. 数据卷容器

    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
    1. 创建数据卷容器
    方式一:docker run -v path IMAGE [COMMAND] [ARG...]
    方式二:构建容器包含VOLUME指令,即容器本身自带数据卷
    例:
    docker run -it -v /dbdata --name dbdata ubuntu

    2. 其它容器通过使用--volumes-from来挂载dbdata容器中的数据卷
    docker run -it --volumes-from dbdata --name db1 ubuntu
    docker run -it --volumes-from dbdata --name db2 ubuntu
    说明:
    此时,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。
    可以多次使用--volumes-from参数来从多个容器挂载多个数据卷。还可以从其他已经挂载了容器卷的容器来挂载数据卷,即多重挂载。
    使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态。
    注意:
    如果删除了挂载的容器(包括dbdata、db1和db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用docker rm -v命令来指定同时删除关联的容器。

    3. 数据卷的备份和还原
    备份:
    docker run --volumes-from [container name需要备份的数据卷容器名称] -v $(pwd):/backup --name backup ubuntu tar cvf /backup/backup.tar [container data valume数据卷容器需要备份的数据卷目录]
    说明:
    首先利用ubuntu镜像创建了一个容器backup。使用--volumes-from参数来让backup容器挂载需要备份的数据卷,使用-v $(pwd):/backup参数来挂载本地的当前目录到backup容器的/backup目录。backup容器启动后,使用了tar命令压缩需要备份的数据,并存放在/backup/backup.tar上(实际就是主机的$(pwd)目录);

    还原:
    docker run --volumes-from [container name] -v $(pwd):/backup --name restore ubuntu tar xvf /backup/backup.tar [container data volume]
    说明:
    跟备份原理相同
  9. Docker的启动配置选项

    1
    2
    3
    1. 启动选项
    参考文档:https://docs.docker.com/engine/reference/commandline/cli/
    docker -d [OPTOINS]
  1. 容器的网络连接

    1

  2. 容器跨主机的网络连接

    1