Docker——操作篇
以前学习 Docker 的笔记,主要是一些 Docker 的操作。
使用 Docker 镜像
Docker 运行容器前需要本地存在对应的镜像,如果镜像没保存在本地, Docker 会尝试先从默认镜像仓库下载(默认使用 Docker Hub 公共注册服务器中的仓库),也可以通过配置,使用自定义的镜像仓库。
获取镜像
使用 docker pull
命令直接从 Docker Hub 镜像源来下载镜像。命令格式
1 | docker pull NAME[: TAG] |
docker pull
命令 NAME
中还应包含 registry
默认为 docker hub
,即 registry.hub.docker.com
,如果从其他 registry
中下载镜像
1 | docker pull hub.c.163.com/public/ubuntu:14.04 |
- pull 命令支持的选项
- a, –all-tags=true|false: 是否获取仓库中所有镜像,默认为否
查看镜像信息
使用 images
命令列出镜像
1 | docker images |
上面命令可以列出本地主机上已有镜像的基本信息
1 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
- REPOSITORY 来自于哪个仓库
- TAG 镜像的标签信息
- IMAGE ID 镜像的 ID
- CREATED 创建时间,说明镜像的最后更新时间
- VIRTUAL SIZE 镜像大小
images 子命令主要支持的选项
- -a, –all=true|false : 列出所有的镜像文件(包括临时文件),默认为false
- –digests=true|false : 列出镜像的数字摘要值,默认为false
- -f, –filter=[] : 过滤列出的镜像,
- –format=”TEMPLATE” : 控制输出格式,如 ID 代表 ID 信息, Repository 代表仓库信息等
- –no-trunc=true|false : 对输出结果中太长的部分是否进行截断,如镜像的 ID 信息,默认为 true
- -q, –quiet=true|false : 仅输出 ID 信息,默认为 false
使用 tag 命令添加镜像标签
1 | docker tag ubuntu:latest mybuntu:latest |
添加一个新的 myubuntu:latest
镜像标签
使用 inspect
命令查看详细信息
1 | docker inspect mybuntu:14.04 |
返回的是 JSON 格式的长信息,如果只需要其中一项内容时,可以使用参数 -f 来指定。
1 | docker inspect -f {{".Architecture"}} |
使用 history
命令查看镜像历史
1 | docker history centos:7.0 |
过长的命令会被自动截断,可以使用 --no-trunc
选项输出完整命令
1 | docker history --no-trunc centos:7.0 |
搜寻镜像
使用 docker search
命令可以搜索远端仓库中共享的镜像,默认搜索官方仓库中的镜像。用法为 docker search TERM
,支持的参数主要包括
- –automated=true|false : 仅显示自动创建的镜像,默认为 false
- –no-trunc=true|false : 输出信息不截断显示,默认为 false
- -s, –stars=X : 指定仅显示评价为指定星级以上的镜像,默认为 0,输出所有镜像
删除镜像
使用标签删除镜像
1 | docker rmi myubuntu:latest |
当某个镜像有多个标签时,删除指定的标签,而不会删除标签所指向的镜像。但当镜像只有一个标签时,会将镜像彻底删除
使用镜像 ID 删除镜像
1 | docker rmi IMAGEID |
当有容器在运行时,无法删除,可以使用 -f
选项进行强制删除
创建镜像
创建镜像的方式有三种:
- 基于已有镜像的容器创建
- 基于本地模板导入
- 基于 Dockerfile 创建
基于已有镜像的容器创建
命令格式:
1 | docker commit[OPTIONS]CONTAINER[REPOSITORY[: TAG]] |
主要选项包括:
- -a, –author=””: 作者信息
- -c, –change=[]: 提交的时候执行 Dockerfile 指令
- -m, –message=”” : 提交消息
- -p, –pause=true : 提交时暂停容器运行
1 | docker commit -m "new file" -a "sjl" c8ac5a420141 test:1.0 |
基于本地模板导入
用户可以直接从一个操作系统模板文件中导入一个镜像,主要使用 docker import
命令,其命令格式为
1 | docker import[OPTIONS] file|URL|-[REPOSITORY[:TAG]] |
未测试
存出和载入镜像
存出镜像
如果要导出镜像到本地文件,可以使用 docker save
命令。
1 | docker save -o outputpath image |
演示命令
1 | docker save -0 centos_7.0.tar centos:7.0 |
载入镜像
可以使用 docker load
命令将导出/存出的镜像导入到本地镜像库
1 | docker load centos_7.0.tar |
上传镜像
使用 docker push
命令上传镜像到仓库,默认上传到 Docker Hub
官方仓库,其命令格式为:
1 | docker push NAME[:TAG]|[REGISTRY_HOST [:REGISTRY_PORT]/]NAME[:TAG] |
未测试,注册 docker hub 或阿里云 docker 账号后进行测试
操作 Docker 容器
容器是 docker
另一个核心概念,容器是镜像的运行实时。镜像是静态只读文件,而容器带有运行时需要的可写文件层。
创建容器
新建容器
新建容器使用 docker create
命令
1 | docker create -it centos:7.0 |
使用 docker crate
命令新建的容器处于停止状态,可以使用 docker start
命令来启动它。
启动容器
使用 docker start
命令来启动一个已经创建的容器
1 | docker start ID |
使用 docker ps -a
查看所有镜像 docker ps
查看一个运行中的容器
新建并启动容器
容器启动步骤
docker create
创建容器docker start
启动容器
使用docker run
命令将创建容器和启动容器合并成一个步骤当利用1
docker run centos:7.0 /bin/echo 'hello world!'
docker run
来创建并启动容器时,Docker
在后台运行操作:- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建一个容器,并启动该容器
- 分配一个文件系统给容器,并在只读的镜像外面挂载一层可读写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口到容器中
- 从网桥的地址池配置一个 IP 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被自动终止
使用 Ctrl + d
或输入 exit
命令来退出容器
常见的错误代码
- 125 : Docker daemon 执行出错,例职指定了不支持的 Docker 命令参数
- 126 : 所指定命令无法执行,例如权限出错
- 127 : 容器内命令无法找到
守护态运行
正常的生产环境下,我们需要让 Docker 容器在后台以守护态(Daemonized)形式运行,此时可以通过添加 -d
参数来实现
1 | docker run -d centos:7.0 |
获取容器的输出信息
1 | docker logs id |
终止容器
使用 docker stop
来终止一个运行中的容器。该命令格式为 docker stop[-t|--time[=10]][CONTAINER...]
首先向容器发送 SIGTERM 信号,等待一段超时时间(默认为 10 秒)后,再发送 SIGKILL 信号来终止 容器
1 | docker stop id |
docker kill
docker kill
命令会直接发送 SIGKILL 信号来强行终止容器。
当 Docker
容器中指定的应用终结时,容器也会自动终止
处于终止状态的容器,可以通过 docker start
命令来重新启动
重启容器
1 | docker restart id |
会将一个运行状态的容器先终止,然后再重启
进入容器
使用 -d
参数启动的 docker 容器,无法看到容器的信息,也无法进行操作,此时如果需要进入容器进行操作,有多种方法:
attach 命令
1 | docker attach [--detach-keys[=[]]] [--no-stdin] [--sig-proxy[[=true]]CONTAINER |
支持三个主要选项
- –detach-keys[=[]] : 指定退出 attach 模式的快捷键序列,默认是 CTRL -P CTRL -Q
- –no-stdin=true|false : 是否关闭标准输入,默认是保持打开
- -sig-proxy=true|false : 是否代理收到的系统信号给应用进程,默认为 true
exec 命令(推荐)
docker 从 1.3.0 提供了一个更加方便的 exec
命令,可以在容器内直接执行任意命令
1 | docker exec [-d|--detach][--detach-keys[=[]]][-i|--interactive][--privileged][-t|--tty][-u|--user[=USER]]CONTAINER COMMAND [ARG...] |
参数:
- -i, –interactive=true|false : 打开标准输入接受用户输入命令,默认为 false
- –privileged=true|false : 是否给执行命令以最高权限,默认为 false
- -t, –tty=true|false : 分配伪终端,默认为 false
- u, –user=”” : 执行命令的用户名或 ID
1
docker exec -it id /bin/bash
nsenter 工具
额外安装工具包
删除容器
使用 docker rm
命令来删除处于终止或退出状态的容器,其命令格式为 `docker rm[-f|–force][-l|–link][-v|–volumes]CONTAINER[CONTAINER…]
主要支持的选项
- -f, –force=false : 是否强行终止并删除一个运行中的容器
- -l, –link=false : 删除容器的连接,但保留容器
- -v, –volumes=false : 删除容器挂载的数据卷
导出和导入容器
导出容器
导出容器是指导出一个已经创建的容器到一个文件,不管此时这个容器是否牌运行状态,可以使用 docker export
命令,该命令的格式为
1 | docker[-o|--output[=""]]CONTAINER |
通过 -o
选项来指定导出的 tar
文件名,也可以直接通过重定向来实现
导入容器
导出的文件可以使用 docker import
命令变成镜像,该文件格式为:
1 | docker import [-c|--change[=[]]][-m|--message[=MESSAGE]]file|URL|-[REPOSITORY[:TAG]] |
用户可以通过 -c, --change=[]
选项在导入的同时执行容器进行修改的 Dockerfile
指令
docker load
和 docker import
的区别
两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也更大。
容器快照文件导入时可以重新指定标签等元数据信息
访问 Docker 仓库
仓库(Repository)是集中存放镜像的地方,分公有仓库和私有仓库。仓库存放在注册服务器上,一个注册服务器可以有多个仓库,一个仓库下可以有多个镜像
Docker Hub 公有镜像市场
登录
通过命令行执行 docker login
命令来输入用户名、密码和邮箱来完成注册和登录。注册成功后,本地用户目录的 .dockercfg
中将保存用户的认证信息
基本操作
用户无需登录即可通过 docker search
命令来查找官方仓库中的镜像,并利用 docker pull
命令来将它下载到本地
自动创建
- 待测试
时速云镜像市场
查看镜像
访问 https://hub.tenxcloud.com , 即可看到已存在的仓库和存储的镜像
下载镜像
下载镜像使用 docker pull
命令,需要在镜像名称前添加注册服务器的具体地址。格式为:
index.tenxcloud.com/<namespace>/<repository>:<tag>
搭建本地私有仓库
使用 registry 镜像创建私有仓库
安装 Docker
后,可以通过官方提供的 registry
镜像来简单搭建一套本地私有仓库环境
1 | docker run -d -p 50000:50000 registry |
管理私有仓库
查看系统已经有镜像
使用 docker push 上传标记的镜像
Docker 数据管理
数据卷
数据卷本质上是将一个 Linux 中的目录映射到容器中,数据卷存在在物理机(宿主机)之上,不会因为删除容器而丢失数据。
挂载目录作为数据卷 -v
1 | 在 /home/sjl/ 下创建 dataVolume 目录 |
映射的目录必须是绝对路径,不允许是相对路径,如果目录不存在, Docker 会自动创建
数据卷权限
在启动容器时,默认的用户权限是 rw
,即可读写。如果仅仅只是为了可读,需要指定为 ro
1 | [root@localhost ~]# docker run -it --name centos -v /home/sjl/dataVolume:/home:ro centos /bin/bash |
在数据卷中增加错误提示: touch: cannot touch ‘b.md’: Read-only file system
-v 参数也支持挂载一个文件到 docker 中,但是不推荐这样做
数据卷容器
数据卷容器,就是将一个容器做为数据卷,提供其他容器挂载。其方式类似于数据卷的做法,区别在于使用的是一个容器。
命令 –volumes-from
创建数据卷容器
1 | [root@localhost ~]# docker -it -v /dataVolumes --name data centos |
在容器中操作的所有目录都将会在容器卷 data
中产生,即创建文件,删除文件等都在对应的容器卷中产生。
端口映射与容器互联
端口映射
从外部访问到 Docker 容器中的应用时,我们如果不将容器中的端口开放出来,就不能访问到内部应用,想要实现访问内部应用的功能就必须要将端口开放。端口开放的方法就是将容器中的端口映射为宿主机的端口,通过访问宿主机的端口从而访问容器的端口。
端口映射命令
-p(小写)
-P(大写)
,两个参数的区别在于
- -p(小写)需要手动指定端口
- -P(大写)不需要手动指定端口,自动随机映射宿主机端口
-p(小写)支持的格式有:
- IP:HostPort:ContainerPort : 指定 IP 的指定端口映射
- IP::ContainerPort : 指定 IP 的随机端口
- HostPort:ContainerPort(常用) : 所有 IP 的随机端口
使用 -P(大写)
随机映射 redis 的端口
1 | [root@localhost ~]# docker run -it -P --name redis redis |
使用 -p(小写)
映射所有宿主机的 IP 的指定端口
1 | [root@localhost ~]# docker run -it -p 16379:6379 --name redis redis |
–name 为容器指定名称,容器名称不能相同,否则不能创建容器。如果容器名称已经存在,要删除之前的容器才能创建。
容器互联
容器互联命令
- –link 参数,可以让容器之间进行互联
容器互联的意义在于,可以直接将容器进行连接,而不通过宿主机,这样就避免了端口暴露在外。常用的就是,在部署应用的容器中,连接数据库的容器,这样就可以直接连接到数据库。1
2[root@localhost ~]# docker run -d --name db mysql:5.7
[root@localhost ~]# docker run -d -P --name web --link db:mysql java
使用 Dockerfile 创建镜像
Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 来快速创建自定义的镜像。
基本结构
Dockerfile 分为四部分:
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
指令说明
FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认会去 Docker Hub 下载指定镜像。格式为 FROM <image> 或 FROM<image>:<tag>,或 FROM <image>@<digest>
任何 Dockerfile 中的第一条指令必须为 FROM 指令,如果同一个 Dockerfile 中创建多个镜像,可以使用多个 FROM 指令。
MAINTAINER
指定维护者信息,格式为 MAINTAINER<name>,该信息会写入生成镜像的 Author 属性域中。
RUN
运行指令命令。格式为 RUN<command> 或 RUN[“executable”, “param1”, “param2”]。
每条 RUN 指令在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。
CMD
CMD 指令用来指定启动容器时默认执行的命令。它支持三种格式:
- CMD[“executable”, “param1”, “param2”] 使用 exec 执行,是推荐的方式
- CMD command param1 param2 在 /bin/bash 中执行,提供给需要交互的应用
- CMD[“param1”, “param2”] 提供给 ENTRYPOINT 的默认参数
如果用户启动容器时手动指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。
LABEL
LABEL 指令用来指定生成镜像的元数据标签信息。格式为 LABEL<key>=<value>…
EXPOSE
声明镜像内服务所监听的端口。格式为 EXPOSE<port>[<port>…]
该指令只是起到声明作用,并不会自动完成端口映射。
ENV
指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。格式为 ENV<key><value> 或 ENV<key>=<value>…
指令指定的环境变量在运行时可以被覆盖的。 docker run –env<key>=<value> built_image
ADD
该命令将复制指定的<src>路径下的内容到容器中的<dest>路径下。格式为:ADD<src><dest>,其中<src>可以是 Dockerfile 所在目录的一个相对路径(文件或目录),也可以是一个 URL,还可以是一个 tar 文件。<dest>可以是镜像内的绝对路径,或者相对于工作目录(WORKDIR)的相对路径。路径支持正则表达式
COPY
复制本地主机的<src>(为 Dockerfile 所在目录的相对路径、文件或目录)下的内容到镜像中的<dest>下。目标路径不存在时,会自动创建。路径同样支持正则表达式。
当使用本地目录为源目录时,推荐使用 COPY
ENTRYPOINT
指定镜像的默认入命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。
支持两种格式:
- ENTRYPOINT [“executable”, “param1”, “param2”](exec 中执行)
- ENTRYPOINT command param1 param2 (shell 中执行)
每个 Dockerfile 中只能有一个 ENTRYPOINT , 当指定多个时,只有最后一个有效。在运行时,可以被 –entrypoint 参数覆盖掉,如 docker run –entrypoint
VOLUME
创建一个数据卷挂载点。格式为 VOLUME[“/data”] 可以从本地主机或其他宫挂载数据卷,一般用来存放数据库和需要保存的数据等。
USER
指定运行容器时的用户名或UID,后续的 RUN 等指令也会使用指定的用户身份。
格式为 USER daemon
WORKDIR
为后续的 RUN、CMD 和 ENTRYPOINT 指令配置工作目录。格式为 WORKDIR/path/to/workdir
可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:
1 | WORKDIR /a |
ARG
指定一些镜像内使用的参数 (例如版本号信息等),这些参数在执行 docker build 命令时才以 –build-arg<varname>=<value> 格式传入。格式为:ARG<name>[=<default value>]
ONBUILD
配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令。格式为 ONBUILD[INSTRUCTION]
STOPSIGNAL
指令所创建镜像启动的容器接收退出的信号值。例如:
1 | STOPSIGNAL signal |
HEALTHCHECK
配置扎启动容器如何进行健康检查(如何判断健康与否),自 Docker 1.12 开始支持。
格式有两种:
- HEALTHCHECK [OPTIONS] CMD command #根据所执行命令返回值是否为 0 来判断
- HEALTHCHECK[OPTIONS] CMD command #根据所执行命令返回值是否为 0 来判断
SHELL
指定其他命令使用 shell 时默认 shell 类型。
默认值为 [“/bin/sh”, “-c”]
创建镜像
编写完成 Dockerfile 之后,可以通过 docker build 命令来创建镜像。
基本格式为 docker build [选项]内容路径,该命令将读取指定路径下(包括子目录)的 Dockerfile,并将该路径下的所有内容发送给 Docker 服务端,由服务端来创建镜像。
- 如果使用非内容路径下的 Dockerfile,可以通过 -f 选项来指定其路径
- 要指定生成镜像的标签信息,可以使用 -t 选项
使用 .dockerignore 文件
可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让 Docker 忽略匹配模式路径下的目录和文件。
例如:
1 | # comment |
使用 Dockerfile 构建 Docker 镜像
- 明日任务,未完成在周末使用 Dockerfile 构建一次镜像
最佳实践
- 精简镜像用途 : 尽量让每个镜像的用途都比较集中、单一,避免构造大而复杂、多功能的镜像;
- 选用合适的基础镜像 : 过大的基础镜像会造成生成臃肿的镜像
- 提供足够清晰的命令注释和维护者个
- 正确使用版本号
- 减少镜像层数
- 及时删除临时文件和缓存文件
- 提高生成速度
- 调整合理的指令顺序
- 减少外部源的干扰
实战案例
使用官方镜像创建容器
busybox 的安装
1 | [root@localhost ~]# docker pull busybox |
Ubuntu 的安装
1 | [root@localhost ~]# docker run -it ubuntu /bin/bash |
CentOS 的安装
1 | [root@localhost ~]# docker run -it centos /bin/bash |
Nginx 的安装
1 | [root@localhost ~]# docker run -d --name nginx -p 80:80 -p 443:443 nginx |
在启动 nginx
的时候,可以添加 -v 选项指定目录
Jenkins 的安
1 | [root@localhost ~]# docker run -p 8080:8080 -p 50000:50000 --name myjenkins jenkins |
使用断卷容器映射出 Jenkins 的操作目录
数据库相关容器的创建
- MySQLdocker 容器互联,应用容器连接至数据库容器
1
[root@localhost ~]# docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 mysql
- 日志
- 配置文件
- 自定义配置文件
- 使用命令传入
- MongoDB
1
[root@localhost ~]# docker run -d --name mongodb -p 27017:2 mongo