docker 使用记录
docker 用的太水了 要学习一波怎么骚操作
安装
wget -qO- https://get.docker.com/ | sh
配置
配置 docker 服务
配置 docker 用户组
sudo usermod -aG docker USER_NAME
docker 服务默认配置
/etc/default/docker
可通过修改其中的 DOCKER_OPTS 来修改服务启动的参数
镜像
使用 docker pull
命令可以拉取镜像
docker pull NAME[:TAG]
NAME 是镜像仓库的名字, 用来区分镜像, TAG 是镜像的标签, 常用来表示版本信息
通常情况下, 描述一个镜像需要 “名字 + 标签”
对于 docker 镜像, 如果不显示指定 TAG, 则默认会选择 latest 标签
镜像仓库名称中应该添加仓库地址(即 registry, 注册服务器)作为前缀, 我们默认的是
docker hub
服务, 该前缀可以省略
下载 ubuntu 镜像:
1 |
|
查看镜像信息
docker images
images 子命令支持如下选项
-a, --all=true|false
所有镜像文件(包括临时文件), 默认为 false--digests=true|false
镜像的数字摘要值 默认为 false-f , --filter=[]
过滤列出的镜像, 如dangling=true
只显示没有被使用的镜像; 也可指定带有特定标注的镜像--format="TEMPLATE"
控制输出格式, 如.ID
代表 ID 信息,.Repository
代表仓库信息--no-trunc=true|false
对输出结果中太长的部分进行截断, 默认为 true-q, --quiet=true|false
仅输出 ID 信息
使用 tag 命令添加镜像标签
docker tag ubuntu:latest myubuntu:latest
使用 inspect 命令查看详细信息
docker inspect ubuntu:latest
使用 history 查看镜像历史
可以使用 history 命令查看各层的创建信息
docker history ubuntu:latest
搜索镜像
使用 docker search 搜索仓库中共享的镜像
docker search TERM
参数:
--automated=true|false
仅显示默认创建的镜像, 默认为 false--no-trunc=true|false
输出信息不截断, 默认为 false-s, --starx=X
指定显示评价为星级以上的镜像, 默认为 0, 即默认输出所有镜像
删除镜像
使用标签删除镜像
docker rmi IMAGE[IMAGE...]
IMAGE 可以为标签或者 ID
当同一个镜像拥有多个标签时, docker rmi
只删除多个标签中的指定标签
当镜像只剩下一个标签时,
docker rmi
会删除镜像
使用镜像 ID 删除镜像
使用 docker rmi
命令根据镜像 ID 删除时,会先尝试删除所有指向该镜像的标签, 然后删除该镜像本身
也可以是能进行区分的部分镜像 ID 串前缀
当该镜像创建的容器存在时, 镜像无法被删除
创建镜像
创建镜像的方法主要有三种: 基于已有的容器创建, 基于本地模板导入, 基于 dockerfile 创建
导出和载入镜像
docker save
, docker load
save 导出镜像到文件
docker save -o ubuntu_14.04.tar ubuntu:latest
载入镜像
docker load --input ubuntu_14.04.tar
或
docker load < ubuntu_14.04.tar
上传镜像
docker push NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]
容器
创建容器
新建容器
docker create
-l, --label=[]
以键值对的方式制定容器的标签信息--label-file=[]
从文件中读取标签信息
docker create -it ubuntu:latest
使用 docker create 命令创建的容器处于停止状态, 可以使用 docker start
启动
启动容器
docker start
新建并启动容器
docker run
docker run ubuntu /bin/echo/ 'hello world'
当使用 docker run
来创建并启动容器时, docker 在后台运行的操作:
- 检查本地是否存在指定的镜像, 不存在则从公共仓库下载
- 使用镜像创建一个容器, 并启动
- 分配一个文件系统给容器, 并在只读的镜像层外面挂载一层可读写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口到容器
- 从网桥的地址池中配置一个 IP 给容器
- 执行用户制定的应用程序
- 执行完毕后容器自动终止
如下命令启动一个 bash, 允许用户进行交互
docker run -it ubuntu:latesd /bin/bash
-t
让 docker 分配一个伪终端并绑定到容器的标准输出上-i
让容器的标准输入保持打开
常见错误码
- 125 docker deamon 执行出错, 例如指定了不支持的 docker 参数
- 126 指定的命令无法执行, 例如权限出错
- 127 容器内命令无法找到
在执行 docker run 的时候 添加 -rm 命令, 则容器在停止后会立即删除
–rm 和 -d 参数不能同时使用
后台运行
可以通过添加 -d
参数实现
停止容器
docker stop[-t|--time[=10]][CONTAINEWR..]
首先向容器发送 SIGTERM 信号, 等待一段时间(默认 10 秒) 后, 再发送 SIGKILL 信号来停止容器
docker kill
命令会直接发送 SIGKILL 信号强行 kill 容器
docker restart
进入容器
attach
attach
是 docker 自带的命令
docker attach [--detach-keys[=[]]] [-no-stdin] [--sig-proxy[=true]] CONTAINER
--detach-keys[=[]]
指定退出 attach 模式的快捷键序列, 默认是CTRL_p, CTRL-q
--no-stdin=true|false
是否关闭标准输入, 默认 false--sig-proxy=true | false
是否代理收到的系统信号给应用进程, 默认 true
当多个窗口同时使用 attach 命令连到同一个容器的时候, 所有窗口都会同步显示. 当某个窗口因命令阻塞时, 其他窗口也无法执行操作.
exec
docker 在 1.3.0 版本起提供了一个更加方便的 exec 命令, 可以在容器内直接执行任意命令.
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
例如 进入刚创建的容器并启动一个 bash
docker exec -it ID /bin/bash
nsenter 工具
在 util-linux 软件包版本 2.23+ 中包含 nsenter 工具
删除容器
docker rm [-f | --force] [-l | --link] [-v |--volumes] CONTAINER[CONTAINER...]
-f, --force=false
rm -f-l, --link=false
删除容器的链接, 但保留容器-v, --volumes=false
删除容器挂载的数据卷
容器的导入和导出
导出
docker export [-o | --output[=""]] CONTAINER
导入
docker import [-c | --changes[=[]]] [-m | --message[=MESSAGE]] file | URL | - [REPOSITORY] [:TAG]
-c, --changes
在导入时执行对容器修改的 dockerfile 指令
数据管理
- 数据卷 容器内数据直接映射到本地主机环境
- 数据卷容器 使用特定容器维护数据卷
数据卷
数据卷是一个可供容器使用的特殊目录, 将操作系统目录直接映射进容器, 类似于 linux 下的 mount 操作
- 数据卷可以在容器之间共享和重用
- 对数据卷内数据的修改会立马生效, 无论是容器内操作还是本地操作
- 对数据卷的更新不会影响镜像, 解耦应用和数据
- 卷会一直存在, 直到没有容器使用, 可以安全卸载
在容器内创建一个数据卷
在用 docker run 命令的时候, 使用 -v 标记可以在容器内创建多个数据卷, 多次重复使用 -v 可以创建多个数据卷
挂载一个主机目录作为数据卷
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
挂载主机的 /src/webapp
目录到容器的 /opt/webapp
目录
也可通过 ro
指定为只读
docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py
这样, 容器内则无法修改挂载的数据
挂载一个本地主机文件作为数据卷
docker run -rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
这样就可以记录在容器输入过的历史命令
若直接挂在一个文件到容器, 使用文件编辑工具, 包括
vi
或者sed--in-place
的时候, 可能会造成文件 inode 的改变, 从 docker 1.1.0 起, 会导致错误发生, 所以推荐的方式是直接挂载文件所在的目录
数据卷容器
如果需要在多个容器之间共享一些持续更新的数据, 最简单的方式是使用数据卷容器.
数据卷容器也是一个容器, 但是它的是专门用来提供数据卷供其它容器挂载
首先, 创建一个数据卷容器 dbdata, 并在其中创建一个数据卷挂载到 /dbdata
docker run -it -v /dbdata --name dbdata ubuntu
然后在其它容器中使用 --volumes-from
来挂载 dbdata 容器中的数据卷
创建 db1 和 db2 两个容器, 并从 dbdata 容器挂载数据卷
docker run -it --volumes-from dbdata --name db1 ubuntu
docker run -itd --volumes-from dbdata --name db2 ubuntu
使用
--volumes-from
参数所挂载的数据卷的容器自身并不需要保持在运行状态如果删除了挂载的容器( 包裹 dbdata db1 db2), 数据卷并不会被删除
如果要删除一个数据卷, 必须在删除最后一个还挂载着它的容器时显式的使用
docker rm -v
来指定同时删除关联的容器
利用数据卷容器来迁移数据
备份
docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata
- 首先使用 ubuntu 镜像创建了一个容器 worker
- 使用
--volumes-from dbdata
让 worker 容器挂载 dbdata 容器的数据卷 - 使用
-v$(pwd):/backup
来挂载本地的当前目录到 worker 容器的 /backup - worker 启动后, 使用
tar cvf /backup/backup.tar /dbdata
将 /dbdata 下内容备份为容器内的 /backup/backup.tar, 即宿主机当前目录下的 backup.tar
恢复
创建一个带有数据卷的容器 dbdata2
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后创建另一个新容器, 挂在 dbdata2 的容器, 并解压备份文件到所挂载的容器卷中
docker run --volumes-from dbdata2 -v $(pwd):/backup tar xvf /backup/backup.tar
端口映射和容器互联
从外部访问容器应用
通过 -p
或 -P
参数来指定端口映射
-P
docker 会随机映射一个 49000 - 49900 的端口到内部容器开放的网络端口
--p
指定要映射的端口, 并且在指定的端口上只可以绑定一个容器, 支持的格式:IP: HostPort: ContainerPort| IP: :ContainerPort | HostPort: ContainerPort
映射所有接口地址
使用 Host: Port: ContainerPort
格式将本地的 5000 端口映射到容器的 5000 端口
docker run -d -p 5000:5000 training/webapp python app.py
映射到指定地址的指定端口
使用 IP: HostPort: ContainerPort
格式指定映射使用一个特定地址, 比如 localhost
docker run -d -p 127.0.0.1:5000:5000 training/webapp python addp.py
映射到指定地址的任意端口
使用 IP: : ContainerPort
绑定 localhost 的任意端口到容器的 5000 端口, 本地主机会自动分配一个端口
docker run -d -p 127.0.0.1::5000 training/webapp python web.py
查看映射端口配置
使用 docker port 命令来查看当前映射的端口配置, 也可以查看到绑定的地址
docker port ubuntu 5000
容器有自己的内部网络和 IP 地址, 使用
docker inspect ContainerID
可以获取容器的具体信息
互联机制实现便捷访问
容器的互联是一种让多个容器中应用进行快速交互的方式, 它会在源和接收器之间创建链接关系, 接收容器可以通过容器名快速访问到源容器, 而不用指定具体的 IP 地址
自定义容器命名
连接系统根据容器的名称来执行, 因此首先要起一个好名字
使用 --name
可以为容器自定义命名
容器的名称是唯一的
如果已经有一个名字了, 需要先删除之前创建的同名容器
容器互联
使用 –link 参数可以让容器之间安全的进行交互
–link 参数的格式为
--link name: alias
其中 name 是要链接的容器的名称, alias 是这个链接的别名
创建一个新的数据库容器
docker run -d --name db training/postgres
创建一个 web 容器, 并将它链接到 db 容器
docker run -d -P --name web --link db:db trainling/webapp python web.py
此时 db 容器和 web 容器建立互联关系
docker 通过两种方式为容器公开信息
- 更新环境变量
- 更新
/etc/hosts
文件
其中 DB_ 开头的环境变量是供容器链接 db 容器使用的, 前缀采用大写的链接别名
除了环境变量之外, Docker 还添加 host 信息到父容器的
/etc/hosts
文件
Dockerfile
基本结构
Dockerfile 由一行行命令语句组成, 支持 #
开头的注释
一般而言 Dockfile 分为四部分:
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
指令
指令的一般格式为 INSTRUCTION arguments
, 指令包括 FROM MAINTAINER RUN
FROM
- 说明:指定该镜像的基础镜像
- 格式如:
FROM <image>
或FROM <image>:<tag>
- 示例:
FROM centos:7
- 注意:
FROM
一般出现在文件头,且每个镜像都需要有一个FROM
来指定基础镜像。
MAINTAINER
- 说明:指定作者信息
- 格式如:
MAINTAINER <name>
- 示例:
MAINTAINER afreto ""
RUN
- 说明:在构建镜像时执行脚本
- 格式如:RUN
或RUN [“exec”, “par1”, “par2”], 后一个指令会被解析成 json 数组, 因此必须使用双引号 , 前者默认将在 shell终端中运行命令. 后者则使用 exec 执行, 不会启动 shell环境, 指定使用其它终端类型可以通过第二种方式实现, 如 RUN[“/bin/bash”,”-c”,”echo hello”] - 示例:
RUN ls -l
(以详细信息方式列表当前目录下的文件,跟在 shell 终端运行一样)
每条指令会在当前镜像的基础上执行指定命令, 并提交为新镜像
命令过长可以使用
\
来换行
CMD
- 说明:用来指定启动容器时默认执行的命令.
- 格式:
CMD["executable","param1","param2"]
, 使用exec
执行, 是 推荐的方式CMD command param1 param2
在/bin/sh
中执行, 提供给需要交互的应用CMD["param1", "param2"]
提供给ENTRYPOINT
的默认参数
- 示例:
CMD ["ls", "-l"]
- 注意:一个 Dockerfile 中只有一条
CMD
,如果有多条只执行最后一条;在运行容器时如果用户指定了运行命令则 Dockerfile 中的 CMD 将被覆盖。
LABEL
- 说明: 用来指定生成镜像的元数据标签
- 格式:
LABEL<key>=<value><key>=<value>...
- 示例:
LABEL version="1.0"
ENTRYPOINT
- 说明:指定镜像的默认入口命令, 该入口命令会在启动容器时作为根命令执行
- 格式如:
ENTRYPOINT ["exec", "par1", "par2"]
、ENTRYPOINT command par1 par2
- 示例:
ENTRYPOINT ["catalina.sh", "run"]
- 注意:一个 Dockerfile 中只有一条
ENTRYPOINT
,如果有多条只执行最后一条, 在运行时可以被--entrypoint
参数覆盖. 如docker run --entrypoint
EXPOSE
- 说明:让 Docker 暴露容器的端口号,供其他容器使用,在宿主机以外的网络中是无法使用的
- 格式如:
EXPOSE <port> ...
- 示例:
EXPOSE 8080
- 注意:
- 该指令只起到声明作用, 并不会完成端口映射
- 在 Docker 中有两种暴露端口的概念,一种叫
EXPOSE
隐式暴露,只供 Docker 服务内部使用;另一种叫PUBLISH
显式暴露,供外部网络使用,PUBLISH
只是一个概念在 Dockerfile 中没有这个指令。 EXPOSE
只在 Dockerfile 中出现PUBLISH
没有该指令而是通过docker run
命令的参数-p
、-P
或在docker-compose
中的ports
来体现-P
:大写是属于自动映射,将 Dockerfile 中EXPOSE
所暴露的所有端口分别映射到宿主机的随机端口,每次启动或重启容器时端口都可能有所不同-p
:小写是属于固定映射,格式如:-p 宿主端口:容器端口
,宿主端口和容器端口可以是纯数字也可以是一个范围,如:-p 8060-8080:8060-8080
,意为将宿主机的8060
(含)到8080
(含)的端口映射到容器的8060
(含)到8080
(含)端口,需要注意的是在使用范围时,宿主端口个数应该与容器端口个数匹配;但上面这个例子可以写成:-p 7060-7080:8060-8080
,这样宿主的端口就在7060-7080
范围内
ENV
说明:指定环境变量,在 Dockerfile 文件中的后续代码中使用,在容器运行时也可以使用
格式如:
ENV <key> <value>
示例:
ENV tomcat_home /web/tomcat/
指令指定的环境变量在运行时可以被覆盖, 如
docker run --env <key>=<value> IMAGE
ADD
- 说明:复制指定的
<src>
路径下的内容到容器中<dest>
路径下(复制文件夹?) - 格式如:
ADD <src> <dest>
- 示例:
ADD web.jar /web.jar
- 注意:复制指定的
<src>
到容器中的<dest>
,<src>
可以是 Dockerfile 所在目录的一个相对路径,也可以是一个 URL,也可以是一个tar
文件(tar
文件将自动解压成文件目录)
COPY
- 说明:添加文件(夹)到容器
- 格式如:
COPY <src> <dest>
- 示例:
COPY web.jar /web.jar
- 注意:与
ADD
功能相似,只是不能指定 URL,使用本地文件(夹)为源文件时,推荐使用COPY
VOLUME
说明:创建挂载点
格式如:
VOLUME [path]
示例:
VOLUME ["/datas"]
注意:
VOLUME
在原理和概念上与EXPOSE
差不多,都是属于供容器与容器间使用通过
VOLUME
挂载的卷可以供其他容器使用举例说明:
创建一个 Dockerfile 来构建一个镜像,内容如下:
1
2FROM centos
VOLUME ["/web/images", "/web/files"]构建镜像
1
docker build -t "zsl131/test01" .
启动容器
1
docker run -d --name test-root
可以使用命令:
docker inspect test-root
来查看容器详细信息,在Mounts
部份可以看到两个挂载点:/web/images
和/web/files
启动另一个容器来共用这两个挂载卷
1
docker run -it --name test-1 --volumes-from test-root centos
注意:使用
--volumes-from
来指定挂载点,这时容器test-root
和test-1
里面都分别有挂载卷/web/images
和/web/files
,可以启动任意多个容器使用--volumes-from
来共用这些挂载卷,这些容器可以来自不同的镜像。当任何一个容器中的挂载卷中的文件发生变化时其他容器挂载卷中的内容也随之改变。容器
test-root
即使已经停止也可以在启动其他容器时使用--volumes-from test-root
来挂载这些卷,只要test-root
不被删除,不过如果test-root
真被删除还可以使用--volumes-from test-1
,因为容器test-1
中还存在我们所需要的挂载卷,换句话说这些挂载卷永远存在直到所有使用这些挂载卷的容器都被删除。VOLUME
与docker run
参数-v
是有区别的。docker run -v /host/web/images:/web/images -v /host/web/files:/web/files:rw
是将容器内的/web/images
挂载到宿主机的/host/web/images
目录上;将容器内的/web/files
挂载到宿主机的/host/web/files
目录上,rw
表示可读写。
WORKDIR
- 说明:设置工作目录
- 格式如:
WORKDIR /path
- 示例:
WORKDIR /web
- 注意:可以使用绝对路径,也可以使用相对路径,设置之后的所有操作都将在这个目录下完成
RUN
、CMD
、ENTRYPOINT
执行脚本的指令
- 三个指令都是执行脚本
RUN
是在创建镜像是执行,即使用docker build
命令时执行,在一个 Dockerfile 里面可以有多个RUN
CMD
和ENTRYPOINT
是在运行容器时执行,即使用docker run
命令时执行,这两个指令在 Dockerfile 中都只有最行一条被执行CMD
在使用docker run
时可以加参数将 Dockerfile 中的CMD
覆盖ENTRYPOINT
在 Dockerfile 中出现后就一定会在docker run
时被执行,不必担心会被其他参数所覆盖。
ADD
、COPY
拷贝文件(夹)到容器
ADD
拷贝文件(夹)时可以指定本地文件、远程 URL 地址,如果拷贝的是tar
文件时将会被自动解压成文件夹COPY
拷贝文件(夹)时不可以指定远程 URL 地址,拷贝tar
文件也不会被自动解压成文件夹,在拷贝本地文件时建议使用COPY
USER
- 说明 指定运行容器时的用户名或 UID, 后续的
RUN
等指令也会使用指定的用户身份 - 格式
USER daemon
ARG
- 说明 指定一些镜像内使用的参数, 这些参数在执行
docker build
命令时以--build-arg<varname>=<value>
格式传入 - 格式
ARG <name>[=<deafult value>]
创建镜像
写完 Dockerfile 后, 使用 docker build
创建镜像
-f
指定 Dockfile 路径-t
指定生成镜像的标签信息
配置代理
docker build . --build-arg "HTTP_PROXY=http://127.0.0.1:1087/" --build-arg "HTTPS_PROXY=http://127.0.0.1:1087/" --network host -t smtp:1