添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Docker 由 Docker 公司开发,是一个能把应用程序自动部署到容器的开源引擎。

官网:https://www.docker.com/

大多数 Docker 容器启动非常快速,同时一台宿主机也可以运行很多容器,使用户可以充分利用系统资源。

Docker 让开发人员和运维人员的职责分离,开发人员只需要关心容器中运行的程序,运维人员只需要关心如何管理容器。

Docker 还鼓励面向服务的架构和微服务架构,推荐单个容器只运行一个应用程序或进程,组成分布式的应用程序模型,使扩展和调试应用程序变得简单。

Docker 包含三个基本概念:

  • 镜像(Image):镜像相是一个 root 文件系统,用户基于镜像来运行容器。
  • 容器(Container):容器基于镜像启动,容器中可以运行一个或多个进程,是镜像运行的实体。
  • 仓库(Registry/Repository):Registry 是镜像仓库平台,保存用户构建的镜像,分为公有和私有,Docker 公司的公共 Registry 叫做 Docker Hub,用户可以下载和上传镜像,也可以架设自己的私有 Registry。而 Repository 指的是 Registry 中某个用户下的某个仓库,和 Github 中的仓库类似。
  • Docker Hub 是官方的 Registry,地址为:https://hub.docker.com/。也可以在本地运行自己的 Registry,对应的镜像为 registry。

    1.1 架构

    Docker 是客户端/服务器(C/S)架构的程序,客户端只需向服务器或守护进程发出请求,服务器或守护进程完成所有工作并返回结果。Docker 提供了一个命令行工具 docker 来与守护进程交互,客户端可以访问本机的守护进程,也可以连接到另一台宿主机上的守护进程。

    Docker 结构如下图所示,客户端连接到守护进程,守护进程会访问在本地的镜像以及仓库中的镜像,并且创建和管理容器。

    1.2 镜像

    Docker 镜像是由文件系统叠加而成的。镜像的最底端是一个引导文件系统 bootfs,往上一层是容器中的基础镜像,是某种操作系统如 Ubuntu 或 Debian 等,而上面还会有 0 到多层的镜像,每一层表示基于镜像的修改再次提交的改动叠加,最上面一层则是容器,是从镜像启动创建容器后的空间。

    Docker 使用联合加载(union mount)技术,对于从内核到基础镜像到多层镜像的文件系统叠加到一起,最终封装为包含所有底层的文件和目录的镜像文件。除了容器这一层可以读写,下面的其他层都是只读的。

    这样一层层的镜像堆叠,位于下面的镜像称为父镜像(parent image),依此类推知道镜像栈最底部的基础镜像(base image)。当从一个镜像启动容器时,Docker 会在该镜像的最顶层加载一个读写文件系统,执行我们指定的程序或命令。

    Dockerfile

    Dockerfile 是一个定义文件,它使用基于 DSL(Domain Specific Language)语法的指令,用来构建一个 Docker 镜像。

    首先我们需要创建一个空目录,进入该目录,创建 Dockerfile 并在里面编辑。这个目录称为构建环境(build environment),这个环境称为上下文(context),Docker 将会在构建镜像时将上下文中的文件和目录上传到 Docker 守护进程,守护进程就能直接访问到用户想存储到镜像的任何代码、文件、数据。

    mkdir my_image
    cd my_image
    touch Dockerfile
    

    Dockerfile 指令大体上的流程是:从基础镜像运行一个容器,执行一条指令,对容器作出修改,然后提交一个新的镜像层,再基于提交的镜像运行一个新的容器,执行下一条指令,直到所有指令执行完毕。

    如果 Dockerfile 某条指令由于某些原因失败了,用户将得到一个可以使用的镜像,这对调试很有帮助。当构建过程失败时,可以将生成的镜像用 docker run 来构建容器,然后再在运行的容器内执行失败的命令,从而发现问题,然后就可以修改 Dockerfile 并再次尝试构建。

    Dockerfile 的每条指令都是大写,注释以 # 开头。

    下面是一个 Dockerfile 的例子。

    # nginx server
    FROM ubuntu:12.04
    MAINTAINER moondo "a.mail.com"
    RUN apt-get update && apt-get install -y nginx
    RUN echo 'this is a new container' > /usr/share/nginx/html/index.html
    EXPOSE 80
    

    每个 Dockerfile 的第一条指令必须是 FROM 指令,它指定一个已存在的镜像作为基础镜像(base image)。

    MAINTAINER 指令标识该镜像的作者和邮件地址。

    RUN 指令在当前镜像运行指定命令,并创建一个新的镜像层。指令默认使用命令包装器 /bin/sh -c,使用 exec 格式的 RUN 指令可以避免不支持 shell 的平台或不希望使用 shell 运行。

    # 使用 /bin/sh -c 运行
    RUN apt-get install -y nginx
    # exec 格式,不使用默认命令包装器,Docker 推荐形式
    RUN ["apt-get","install","-y","nginx"]
    

    EXPOSE 指令告诉 Docker 该容器内的应用程序将使用的容器内端口,创建容器时并不会因此自动打开该端口,需要在创建容器时指定。

    Dockerfile 常用指令如下:

    # FROM 指定基础镜像
    FROM ubuntu:12.04
    # MAINTAINER 标识该镜像的作者和邮件地址
    MAINTAINER moondo "a.mail.com"
    # ENV 设置环境变量
    ENV PATH /root
    # RUN 运行命令,并创建一个新的镜像层
    RUN apt-get update && apt-get install -y nginx
    # CMD 指定容器启动时运行的命令
    # docker run 传入的命令可以覆盖 CMD 指令,不指定则会执行 CMD 指定的命令
    # 一个 Dockerfile 只能指定一条 CMD 指令,如果有多条,只有最后一条会被使用
    CMD /bin/bash -l
    # ENTRYPOINT 指定容器启动时运行的命令,相比 CMD 不会被 docker run 的命令覆盖
    # docker run 的 --entrypoint 可以覆盖该指令
    ENTRYPOINT ["/usr/sbin/nginx"]
    # EXPOSE 声明应用程序将使用的容器内端口
    EXPOSE 80
    # WORKDIR 在容器内部设置工作目录,CMD 和 ENTRYPOINT 将在该目录执行
    WORKDIR /opt/myapp
    # USER 指定运行时的用户,不指定则默认为 root
    USER nginx
    # VOLUME 向容器添加卷
    # 一个卷可以存在于一个或多个容器的特定目录,在容器间共享,对卷的修改不影响镜像,卷会一直存在直到没有任何容器使用它
    # 可以将数据、代码等内容添加到镜像,而不用提交到镜像,从而在多个容器间共享内容
    VOLUME ["/opt/project"]
    # ADD 将构建环境的文件和目录复制到镜像中
    # 只能添加构建目录中的文件或目录,文件源也可以是 URL 格式
    Add a.lic /opt/myapp/a.lic
    # COPY 将构建环境的文件和目录复制到镜像中
    # 只复制文件,不能使用 URL,也不会提取和解压文件
    COPY conf.d/ /etc/nginx/
    # STOPSIGNAL 设置容器停止时发送的系统信号,可以用信号的数字或名称
    STOPSIGNAL SIGKILL
    # ARG 定义可以在构建镜像时传递进来的变量
    # 如在构建时使用 --build-arg env=prod,可以预先赋值作为默认值
    ARG env
    ARG env=prod
    # ONBUILD 添加触发器,当镜像被其它镜像作为基础镜像时,触发执行指令
    ONBUILD ADD . /app/src
    

    CMD 指令会被 docker run 的指令覆盖,ENTRYPOINT 指令不会被覆盖,可以通过以下方式来实现默认参数和可选参数。当 docker run 不指定命令,则以 ENTRYPOINT 作为命令而以 CMD 中的指令为参数,如果指定了则还会使用 ENTRYPOINT 的指令,但是会覆盖 CMD 的指令。

    ENTRYPOINT ["/usr/sbin/nginx"]
    CMD ["-h"]
    

    2. 命令

    2.1 服务器

    查看 Docker 程序状态,该命令会返回所有容器和镜像的数量、驱动程序、存储驱动、以及基本配置。

    docker info
    

    2.2 仓库

    登陆到 Docker 镜像仓库,如果没有指定镜像仓库地址,默认为 Docker Hub。

    docker login
    # 登陆私有仓库
    docker login -u <admin> -p <passwd> <url>
    

    退出登录仓库

    退出登录的仓库。

    docker logout
    

    2.3 镜像

    列出当前机器上可用的镜像。

    docker images
    # 查看指定镜像
    docker images <image>[:<tag>]
    

    从镜像仓库查找可用镜像。

    docker search <image>
    

    从镜像仓库中拉取镜像到本地。

    每个镜像会带有标签,表示不同的版本,默认拉取的是 latest 的镜像,除非指定镜像标签。

    docker pull <image>[:<tag>]
    # 拉取 latest 镜像
    docker pull ubuntu
    docker pull ubuntu:latest
    # 拉取指定标签的镜像
    docker pull ubuntu:12.04
    

    从已有镜像创建的容器修改后创建新的镜像。

  • -m"":指定镜像的提交信息
  • -a"":指定镜像的作者信息
  • docker commit <container> <image>[:<tag>]
    

    使用 Dockerfile 构建镜像,比较推荐这一种方式。

  • -t:指定仓库、名称和标签
  • –build-arg env=prod:构建时传入变量
  • docker build -t <repository>/<image>[:<tag>] <dir>
    # 从当前目录构建镜像
    docker build -t huanglianjing/my_image:v1 .
    # 从 Git 仓库构建镜像
    docker build -t huanglianjing/my_image:v1 [email protected]:huanglianjing/my_image
    

    查看镜像的每一层的指令。

    docker history <image>
    

    删除本地镜像。

    对于镜像仓库上的镜像,需要在浏览器登录然后在页面上操作删除。

    docker rmi <image>
    

    将镜像推送到镜像仓库。

    docker push <image>
    

    2.4 容器

    查看容器列表

    查看已有的容器。

  • -a:查看所有运行中和已暂停的容器,不带改选项只会返回运行中的容器
  • -q:只返回容器 ID
  • # 查看所有容器的列表
    docker ps -a
    # 查看运行中的容器的列表
    docker ps
    

    指定镜像名称和标签,首先检查本地是否存在该标签的镜像,如果没有就从镜像仓库中查找并下载镜像。然后使用该镜像创建一个新的容器,并且执行指定的命令。

    每个容器有它的容器 ID 和名称,创建容器时会自动分配一个随机的名称,也可以在创建时指定名称。

  • –name <container_name>:为容器指定名称
  • -i:开启容器的 STDIN
  • -t:为创建的容器分配一个伪 tty 终端,一遍提供交互式 shell
  • -d:让容器在后台运行,启动守护式的容器
  • -p <port>:控制容器公开给宿主机的网络端口,-p p2 将容器内的 p2 端口随机映射到宿主机 32768~61000 的某个端口,-p p1:p2 将容器内的 p2 端口映射到宿主机的 p1 端口
  • -P:对外公开所有 EXPOSE 指令的端口,绑定到宿主机随机端口上
  • –rm:容器退出后将其删除
  • -v file:file:映射本地文件或目录与容器中的文件或目录
  • –log-driver="":控制容器的日志驱动,默认为 json-file,即开启 docker logs 命令,syslog 将禁用 docker logs 命令并将容器日志输出重定向到 Syslog,none 将禁用所有容器的日志
  • –restart=:设置容器错误停止时的重启条件,always 表示无论容器退出代码是什么都会自动重启,on-failure:5 表示退出代码非 0 才重启,可以设置最多重试 5 次
  • –entrypoint:覆盖 ENTRYPOINT 指令
  • –env:设置环境变量
  • -w <dir>:覆盖 WORKDIR 目录
  • docker run <image>[:<tag>] <cmd>
    # 创建容器并进入交互式终端,exit 命令将会暂停交互式容器
    docker run -i -t ubuntu /bin/bash
    # 创建守护式容器,进行端口映射,后台执行
    docker run -p 8080:80 -d nginx
    # 宿主机访问端口: curl 127.0.0.1:8000
    

    只创建容器而不启动,具体选项和用法与 docker run 一样。

    docker create <image>[:<tag>] <cmd>
    

    启动已经停止运行的容器,可以通过容器 ID 或容器名称来指定。

    docker start <container>
    

    重启一个运行中的容器。

    docker restart <container>
    

    附着在一个运行中的容器,进入交互式终端。

    docker attach <container>
    

    停止运行中的容器。

    # 向容器发送 SIGTERM 信号,对于守护式容器立刻停止,对于交互式容器将等待
    docker stop <container>
    # 向容器发送 SIGKILL 信号,立即退出
    docker kill <container>
    

    启动新进程

    在容器内部额外启动新进程。

    # 运行交互命令
    docker exec -i -t <container> <cmd>
    # 运行后台任务
    docker exec -d <container> <cmd>
    

    获取容器的日志。

  • -f:监控日志追加内容
  • –tail <n>:显示最后 n 行
  • -t:为每条日志加上时间戳
  • docker logs <container>
    # 监控日志追加内容
    docker logs -f <container>
    # 获取日志最后 10 行内容
    docker logs --tail 10 <container>
    # 监控日志追加内容,不需要读取整个日志文件
    docker logs --tail 0 -f <container>
    

    查看容器内部运行的进程。

    docker top <container>
    

    查看容器端口映射情况,容器内的哪个端口映射到了宿主机的哪个端口。

    docker port <container> [<port>]
    

    容器统计信息

    查看一个或多个容器实时更新的的统计信息,包括 CPU、内存、硬盘 IO、网络 IO。

    docker stats <containers>
    

    获取更多容器信息

    获取更多容器信息,包括名称、命令、网络配置等信息。

    docker inspect <containers>
    

    将一个容器删除。

    docker rm <containers>
    

    将本地容器导出为本地文件。

    docker export -o <file> <container>
    docker export <container> > <file>
    

    从容器导出的文件导入为镜像。

    docker import <file>|<url> <image>
    cat <file> | docker import - <image>
    

    3. 参考

  • 《第一本Docker书》
  • Docker — 从入门到实践
  •