操作镜像
获取镜像并启动一个容器
$ docker run -d -p 80:80 --name webserver nginx
查看当前运行的容器
$ docker ps
获取镜像
$ docker pull --help
$ docker pull [OPTIONS] NAME[:TAG|@DIGEST]
$ docker pull ubuntu:14.04
NAME:为镜像仓库名称
TAG:为镜像的标签
查看镜像信息
$ docker images
使用镜像创建容器,运行应用
$ docker run -it ubuntu:14.04 bash
查看当前运行的容器
$ docker ps
给镜像打标签
$ docker tag
查看镜像详细信息
$ docker inspect
例如
$ docker inspect 677
$ docker inspect 677 -f {{".Architecture"}} #获取部分信息
查看镜像历史
$ docker history 677
$ docker history 677 --no-trunc #显示完整的命令
搜索镜像
$ docker search --automated -s 3 nginx #自动创建且3星以上的nginx镜像
删除镜像
通过标签名删除镜像,则删除的是标签,不删除原始镜像。
通过镜像ID删除镜像,先尝试删除所有标签,然后删除镜像本身。
如果镜像有容器存在,则无法删除。可以强制删除,但是不建议这样做。
$ docker rmi TAG
$ docker rmi IMAGE ID
$ docker rmi -f IMAGE ID
创建镜像
1. 基于已有镜像的容器创建
$ docker tag ubuntu:14.04 myubuntu:01
$ docker run -it myubuntu:01 /bin/bash
# touch test
# exit
$ docker ps -a
$ docker commit -a "liux" -m "create file" -p c466799b264e test:01
$ docker images
- 基于本地模板创建
- 基于Dockerfile创建
导出和导入镜像
$ docker save -o ~/Downloads/ubuntu_14.04.tar ubuntu:14.04
$ docker load < ~/Downloads/ubuntu_14.04.tar
上传镜像
$ docker tag ubuntu:14.04 test/myubuntu:01
$ docker push test/myubuntu:01
操作容器
容器是镜像的一个实例,镜像是静态只读文件,而容器带有运行时所需的可写层。
可以认为虚拟机是一套操作系统,可以在上面运行应用。
而容器只是一个可以独立运行的应用,携带了他必需的运行环境。
create命令与容器运行模式相关的选项
选项 | 说明 |
---|---|
-a , –attach=[ ] | 是否绑定到标准输入,输出和错误 |
-d , –detach=true|false | 是否在后台运行容器,默认false |
–detach-keys=”“ | 从attach模式退出时的快捷键 |
–entrypoint=”“ | 镜像存在入口命令时,覆盖为新的命令 |
–expose=[ ] | 指定容器会暴露出来的端口或端口范围 |
–group-add=[ ] | 运行容器的用户组 |
-i, –interactive=true|false | 保持标准输入打开,默认为false |
–ipc=”“ | 容器IPC命名空间,可以为其他容器或主机 |
–isolation=”default” | 容器使用的隔离机制 |
–log-driver=”json-file” | 指定容器的日志驱动类型:json-file,syslog,journald,gelf,fluentd,awslogs,splunk,etwlogs或none |
–log-opt=[ ] | 传递给日志驱动的选项 |
–net=”bridge” | 指定容器网络模式,bridge,none,其他容器内网络,host的网络或某个现有网络 |
–net-alias=[ ] | 容器在网络中的别名 |
-P, –publish-all=true|false | 通过NAT机制将容器标记暴露的端口自动映射到本地本机的临时端口 |
-p, –publish=[ ] | 指定如何映射到本地主机端口,例如:-p 11234-12234:123-12234 |
–pid=host | 容器的PID命名空间 |
–userns=”“ | 启动userns-remap时配置用户命名空间的模式 |
–uts=host | 容器的UTS命名空间 |
–restart=no | 容器的重启策略,包括no,no-failure[:max-retry],always,unless-stopped |
–rm=true|false | 容器退出后是否自动删除,不能跟-d同时使用 |
-t, –tty=true|false | 是否分配一个伪终端,默认为false |
–tmpfs=[ ] | 挂载临时文件系统到容器 |
-v | –volume[=[[HOST-DIR:]CONTAINER-DIR[:OPTIONS]]] | 挂载主机上的文件卷到容器内 |
–volume-driver=”“ | 挂载文件卷的驱动类型 |
–volumes-from=[ ] | 从其他容器挂载卷 |
-w, –workdir=”“ | 容器内默认的工作目录 |
create命令与容器环境和配置相关的选项
选项 | 说明 |
---|---|
–add-host=[ ] | 在容器内hosts文件中添加主机名到ip的映射 |
–device=[ ] | 映射物理机上的设备到容器内 |
–dns-search=[ ] | DNS搜索域 |
–dns-opt=[ ] | 自定义的DNS选项 |
–dns=[ ] | 自定义的DNS服务器 |
-e,–env=[ ] | 指定容器内环境变量 |
–env-file=[ ] | 从文件中读取环境变量到容器内 |
-h,–hostname=”“ | 指定容器内的主机名 |
–ip=”“ | ip |
–ip6=”“ | ip6 |
–link=[:alias] | 链接到其他容器 |
–mac-address=”“ | 指定mac地址 |
–name=”“ | 指定容器别名 |
create命令与容器资源限制和安全保护相关的选项
选项 | 说明 |
---|---|
–blkio-weight=10-1000 | 容器读写块设备的IO性能权重,默认为0 |
–blkio-weight-device=[DEVICE_NAME:WEIGHT] | 指定各个设备的IO性能权重 |
-c, –cpu-shares=0 | 允许容器使用的CPU资源的相对权重,默认一个容器能用满一个核的CPU |
–cap-add=[ ] | 增加容器的linux指定安全能力 |
–cap-drop=[ ] | 移除容器的liunux指定安全能力 |
–cgroup-parent=”“ | 容器cgroups限制的创建路径 |
–cidfile=”“ | 指定容器进程id号写到的文件 |
–cpu-period=0 | 限制容器CFS调度下CPU占用时间片 |
–cpuset-cpus=”“ | 限制容器能使用哪些CPU |
–cpuset-mems=”“ | NUMA架构下使用哪些核心的内存 |
–cpu-quota=0 | 限制容器CFS调度下CPU配额 |
–device-read-bps=[ ] | 挂载设备读吞吐率限制 bps |
–device-write-bps=[ ] | 挂载设备写吞吐量限制 bps |
–device-read-iops=[ ] | 挂载设备读速率 单位为每秒io次数 |
–device-write-iops=[ ] | 挂载设备写速率 单位为每秒io次数 |
–kernel-memory=”“ | 限制容器内存使用大小 |
-m, –memory=”“ | 限制容器内应用内存使用大小 |
–memory-reservation=”“ | 内存过低时,容器被限制内存的指定值 |
–memory-swap= | 限制容器使用内存和交换空间的总大小 |
–oom-kill-disable=true|false | OOM时是否kill容器 |
–oom-score-adj=0 | Tune host’s OOM preferences (-1000 to 1000) |
–pids-limit=”“ | 限制容器pid个数 |
–privileged=true|false | 是否给容器高权限,容器内应用将不受权限限制 |
–read-only=true|false | 是否让容器内文件系统只读 |
–security-opt=[ ] | 指定一些安全参数,包括权限,安全能力,apparmor等 |
–stop-signal=”SIGTERM” | 指定停止容器的系统信号 |
–shm-size=”“ | /dev/shm的大小 |
–memory-swappiness=-1 | 调整容器的内存交换区参数 |
-u, –user=”“ | 指定容器内执行命令的用户信息 |
–ulimit=[ ] | 通过ulimit来限制最大文件数,最大进程数 |
其他重要参数
选项 | 说明 |
---|---|
-l, –label=[ ] | 以键值对方式指定容器的标签信息 |
–label-file=[ ] | 从文件中读取标签信息 |
新建容器
新创建的容器状态为Created
$ docker create -it ubuntu:latest #-it 打开标准输入,并创建伪终端
启动/关闭容器
$ docker start 5cb
$ docker stop 5cb
容器状态
动作 | 状态 |
---|---|
create | Created |
start | Up |
stop | Exited |
使用docker run新建并启动容器
docker run 等价于 先执行docker create 在执行 docker start
$ docker run ubuntu /bin/echo 'Hello World'
docker run后台执行的操作:
- 检查本地是否存在镜像,不存在从仓库下载
- 利用镜像创建一个容器,并启动容器
- 分配一个文件系统给容器,并在只读层外面挂载一层可读写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口道容器中
- 从网桥的地址池中配置一个ip地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器自动终止
docker run常见的错误
错误码 | 错误原因 |
---|---|
125 | Docker daemon执行出错,例如指定了不支持的命令参数 |
126 | 所指定的命令无法执行,例如权限问题 |
127 | 容器内命令无法找到 |
守护态运行容器
-d参数
$ docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello; sleep 1; done"
获取容器的输出信息
$ docker logs CID #CID 容器id
终止容器
$ docker stop CID #CID 容器id
$ docker stop -t 10 CID #10s后终止容器
$ docker kill CID #强制终止
重启容器
$ docker restart CID
restart会将一个运行态的容器先终止然后重新启动
进入容器
当容器使用-d参数运行时,容器自动进入后台。用户无法看到容器中的信息,也无法对容器进行操作。
attach命令
exec命令
$ docker run -itd ubuntu:14.04 $ docker exec -it CID /bin/bash
- nsenter工具
删除容器
$ docker rm [-f|--force] [-l|--link] [-v|columes] CID [CID...]
-f 强制删除,默认只能删除终止或退出状态的容器,-f会先终止,再删除
-l 删除容器链接,保留容器
-v 删除容器挂载的数据卷
容器导入导出
容器可以导出,无论它是否正在运行。导出的容器可以导入变为镜像。导出的容器与导出的镜像相比丢弃了所有的历史记录与元数据信息,体积较小,导入时可以重新执行元数据信息。而镜像所有记录比较完整,体积相对也较大。
#导出
$ docker export -o ./c_export_test.tar ca3
$ docker export ca3 > ./c_export_test.tar
# 导入
$ docker import ./c_export_test.tar test/ubuntu:01
使用Docker仓库
概念
private-docker.com/ubuntu
注册服务器:注册服务器是存放仓库的具体服务器,一个注册服务器上可以存在很多个仓库。private-docker.com是注册服务器地址。
仓库:仓库是存放镜像的地方,一个仓库可以存放很多镜像。ubuntu就是注册服务器下的一个仓库。
$ docker login -u username -p password
$ docker search centos
$ docker pull centos
#将镜像push到仓库
$ docker tag centos:latest jefferliu/centos:01
$ docker pull jefferliu/centos:01
关于自动创建
自动创建的镜像,当镜像内软件有新版本时,不需要手动更新镜像。
创建自动创建的步骤:
- 创建并登陆DockerHub,以及目标网站;因为要在DockerHub连接到目标网站。目前DockerHub支持的目标网站有Github和Bitbucket。
- 在DockerHub上创建一个自动构建;Create > Create Automated Build
- 选择连接到Github或Bitbucket,一个Github或Bitbucket账户只能链接一个DockerHub账户
- 选取一个目标网站中的项目(需要含有Dockerfile)和分支
- 指定Dockerfile的位置,并提交创建
搭建本地私有仓库
先不做
Docker数据管理
容器中管理数据的两种方式:
- 数据卷(Data Volumes):容器内数据直接映射到本地主机环境
- 数据卷容器(Data Volumes Containers):使用特定容器维护数据卷
数据卷
将主机操作系统目录映射到容器内,类似linux的mount。
数据卷的特性:
- 卷可以在容器间共享和重用,容器间传递数据将变得高效方便。
- 对卷内数据的修改立即生效,无论在容器内还是在主机上。
- 对数据卷的更新不影响镜像,解耦了应用和数据。
- 卷会一直存在,直到没有容器使用,可完全卸载。
在容器内创建卷
$ docker run -it -v /dbdata --name dbdata ubuntu
挂载主机目录作为卷
挂载主机目录时,不会影响目录内原有文件与数据
$ docker run -it --name dbdata -v /tmp/docker:/dbdata ubuntu
数据卷容器
可以专门使用一个挂载了卷的容器作为数据卷容器,
# 数据卷容器
$ docker run -it -v /dbdata --name dbdata ubuntu
# 使用数据卷容器的容器 db1 和 db2
$ docker run -it --volume-form dbdata --name db1 ubuntu
$ docker run -it --volume-form dbdata --name db2 ubuntu
删除数据卷
删除挂载数据卷的容器时不会删除数据卷,如果要删除一个数据卷,必须在删除最后一个引用它的容器时指定 -v 参数
$ docker stop dbdata
$ docker rm -v dbdata
删除本地挂载的数据卷后,不影响本地文件夹内的数据和文件
利用数据卷容器迁移数据
# 备份
$ docker run --volumes-from dbdata -v /tmp/docker:/backup --name worker ubuntu tar cxf /backup/backup.tar /dbdata
# 恢复
docker run -v /dbdata --name dbdata2 ubuntu
$ docker run --volumes-from dbdata2 -v /tmp/docker:/backup --name busybox ubuntu tar xvf /backup/backup.tar
端口映射与容器互联
解决多个容器之间能够互相访问对方的服务。容器互联有两种方式,分别是:
- 映射容器内服务端口到本机端口;
- 容器互联机制,通过容器名快速访问;
端口映射
随机接口
使用-P参数
$ docker run -d -P training/webapp python app.py
docker ps -l
-P参数会映射一个49000~49900的端口到容器内部开放的网络端口
指定端口
$ docker run -d -p 5000:5000 training/webapp python app.py
docker ps -l
如果指定了容器内没有应用的服务端口,docker run命令不会失败
容器启动后用docker ps -l 查看容器时PORTS显示的信息为:
0.0.0.0:5000->5000/tcp
映射到非服务端口,PORTS显示的信息为:
5000/tcp, 0.0.0.0:5000->5001/tcp
这能助于排除端口映射是否正确,容器在5000端口提供tcp链接,本地5000端口却映射到5001端口上。
同时指定多个端口
$ docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
docker ps -l
映射到指定地址的指定端口
这种情况当主机有多网卡时有用
# ip地址必须有效
$ docker run -d -p 192.168.1.100:5000:5000 -p 192.168.2.110:3000:80 training/webapp python app.py
docker ps -l
映射到指定地址任意端口
# ip地址必须有效
$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py
docker ps -l
映射UDP端口
# ip地址必须有效
$ docker run -d -p 127.0.0.1::5000/udp training/webapp python app.py
docker ps -l
查看端口映射
$ docker port CID
与docker ps -l 查看容器时PORTS显示的映射信息相反
互联机制
Container linking
会用 –link 参数可以让容器之间安全地进行交互。Docker相当于在两个互联的容器间建立了一个虚拟通道,而且不用映射他们的端口到宿主机上。
Docker通过两种方式为容器公开链接信息:
- 更新环境变量
- 更新host文件
实例
# 创建数据库容器
$ docker run -d --name db training/postgres
$ docker run -d --name web --link db:db training/webapp python app.py
# 进入web容器,查看env和host文件
$ docker exec -it web /bin/bash
使用docker ps查看容器names列中并不能体现互联信息,Version 17.09.1-ce-mac42
在网络环境复杂情况下,容器需要需要跨主机甚至跨数据中心的通信,需要引入额外的机制,例如SDN或NFV。
使用Dockerfile创建镜像
可以使用Dockerfile创建自定义镜像。Dockerfile有其典型的结构,并且支持很多命令。
Dockerfile命令
命令 | 说明 |
---|---|
FROM | 指定所创建镜像的基础镜像 |
MAINTAINER | 维护者信息 |
RUN | 运行命令 |
CMD | 指定启动容器时执行的命令 |
LABEL | 指定生成镜像的元数据标签信息 |
EXPOSE | 生命镜像内服务所监听的端口 |
ENV | 指定环境变量 |
ADD | 复制指定的src/url所指定的内容到dest路径下。若是tar,自动解压,不推荐 |
COPY | 复制指定的src/url所指定的内容到dest路径下。推荐使用 |
ENTRYPOINT | 指定镜像默认入口 |
VOLUME | 创建数据卷挂载点 |
USER | 指定运行容器时的用户名或uid |
WORKDIR | 配置工作目录 |
ARG | 指定镜像内使用的参数 (例如版本信息) |
ONBUILD | 配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作命令 |
STOPSIGNAL | 容器退出的信号值 |
HEALTHCHECK | 如何进行健康检查 |
SHELL | 指定使用shell时默认的shell类型 |
FROM
格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
要创建镜像的基础镜像。若不存在,则去Dockerhub下载。任何Dockerfile第一行命令必须是From指令。
如果在一个Dockerfile中创建多个镜像,可以使用多个FORM命令,每个镜像一次
MAINTAINER
MAINTAINER docker_user docker_user@email.com
该信息会写入生成镜像的Author属性中。
RUN
RUN <command> #在shell终端运行
RUN ["executable" , "param1" , "param2"] #使用exec执行,不启动shell环境
每条run指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 换行
例如:
RUN apt-get update \
&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
&& rm -rf /var/cache/apt
CMD
每个Dockerfile中只能有一个CMD命令。若出现多个,前面的将被覆盖。
如果启动容器时手动指定了运行的命令,则会覆盖CMD指定的命令。
# 推荐使用的方式
CMD ["executable" , "param1" , "param2"] #使用exec执行,不启动shell环境
# 在、bin/sh中执行,提供给需要交互的应用
CMD command param1 param2
# 提供给ENTRYPOING的默认参数
CMD ["param1" , "param2"]
LABEL
用来指定生成镜像的原数据标签信息
LABLE <key>=<value>
例如:
LABEL version="1.0"
LABEL description="this is a fun images"
EXPOSE
生命镜像内服务所监听的端口
EXPOSE port [port , port , ...]
只起到声明作用,并不会自动完成端口映射
要完成端口映射,需要在启动容器时使用-P或-p参数
ENV
指定环境变量,在Dockerfile中会被后续指令中使用,在镜像启动的容器中也会继续存在。
ENV <KEY> <VALUE>
ENV <KEY>=<VALUE>
例如:
ENV JAVA_VARSION 1.7
RUN curl -SL http://downloadjava/${JAVA_VERSION}
ENV PATH /usr/local/java_${JAVA_VERSION}/bin:$PATH
已指定的环境变量在运行时可以使用run命令覆盖,docker run –env =
ADD
复制指定路径下的内容到容器总的目标路径
ADD <src> <dest>
src是相对于dockerfile所在目录的一个相对路径或文件,也可以是一个RUL或tar文件(tar文件上传后会自动解压)。
dest是镜像内的绝对路径或相对于工作目录(WORKERDIR)的相对路径。
例如:
ADD *.java /code/
COPY
与ADD命令功能作用相同。
目标路径不存在时会自动创建。
当使用本地目录为src时,推荐使用COPY。
ENTRYPOINT
指定镜像的默认入口命令,该入口命令会在容器启动时作为跟命令执行,所有传入值作为该命令的参数。
ENTRYPOINT ["executable" , "param1" , "param2"] #使用exec执行
# 在、bin/sh中执行
ENTRYPOINT command param1 param2
当指定ENTRYPOINT后,CMD指令将作为根命令的参数。
Dockerfile中只能有一个ENTRYPOINT,多个时只有最后一个有效,使用docker run –entrypoint参数可以覆盖。
VOLUME
创建一个数据卷挂载点,是点,没有进行挂载
VOLUME ["/data"]
WORKDIR
为后续的RUN , CMD , ENTRYPOINT指令配置工作目录
WORKDIR /path/to/dir
可以使用多个WORKDIR指令,若后续指令参数是相对路径,则会基于指点的指令指定的路径。
ARG
指定镜像内使用的参数,这些参数在执行docker build命令时以–build-arg =形式传入。
ARG <name>=[<default value>]
ONBUILD
配置当前镜像作为其他镜像的基础镜像时,所指定的创建操作指令。等价于在新镜像的Dockerfile中增加的命令。
例如:
ONBUILD ADD . /app/src
ONBUILD RUN ....
HEALTHCHECK
配置所启动容器如何新型健康检查,有两种格式:
- HEALTHCHECK [OPTIONS] CMD command:根据所执行命令是否返回0来判断;
- HEALTHCHECK NONE:禁止健康检查;
OPTION支持:
- –interval=DURATION:检查间隔,默认30s;
- –timeout=DURATION;
- –retries=N:重试几次最终确认失败;
SHELL
指定其他命令使用shell时默认的shell
SHELL ["executable" , "parameters"] #默认["/bin/sh", "-c"]
创建镜像
$ docker build [option]
如果使用非内容路径下的Dockerfile,可以通过-f参数指定其路径。
要指定生成镜像的标签信息,使用-t参数。
例如:
$ docker build -t jefferliu/ubuntu_test:01 /temp/docker
使用.dockerignore文件
在文件中每一行添加一条匹配模式,让Docker忽略匹配模式路径下的目录文件。例如:
# comment
*/temp*
*/*/temp*
tmp?
~*