Docker 学习

快速入门心法

官网文档也好,网上其他的教程也好,都非常有“耐心”,一点点地教你怎么理解和使用 docker,但我在看这些教程和文档的时候其实很着急,因为我只想快速入门并且用起来,而且最好是按最佳实践的路子用起来,而不是象个初学者那样慢慢摸索。但就是没人把这条捷径说清楚……

下面我就我所知道和理解的内容,写一点快速入门的心法:

  • 首先知道 docker 大概是个什么?
    • 就我的理解,直白地说:就是一个轻量的虚拟机,在一个基本的内核基础上,层层叠加出想要的虚拟机环境。
    • 同时要注意一个重要概念,类似于微服务概念,每一个 docker 虚拟机里面一般只做一件事,只支持一个服务,例如: web 服务、 hexo 博客服务等;
  • 其次要知道拿 docker 来有什么用,最主要的用途在哪儿?
    • 目前就我的使用情况来说,就是一些开发部署环境在本机搭建起来很麻烦,不同的操作系统还有所不同,还要在本机安装一堆的包,还要在本机进行很多配置,而使用 docker 之后,就可以不用在本机安装了,本机干净了,又能快捷享用 docker 虚拟机中提供的服务。
    • 保证应用项目在不同的主机上运行时一致,因为都是运行在 docker 中的,所以各种操作系统,各个电脑打开项目,只要正常安装了 docker 后,启动运行起来,都象是在 linux 中一样,因为 docker 虚拟机基本都是基于 linux 操作系统的。
  • 如何快速入门使用?
    • 首先要有一定的基础,否则会遇到太多阻碍,个人觉得是要对 linux 系统的基础操作和一些工作模式要有一定的熟悉和了解,特别是网络方面比较清楚会有比较大的帮助,另外了解 git 的使用流程和基本命令会比较有帮助,对于理解 docker 这种虚拟机的管理模式也会比较有帮助,当然有一定的编程基础,熟悉一些语言开发也是必须的,毕竟 docker 就是帮助开发部署环境用的。
    • 快捷路线就是 docker-compose 了,别在 docker 命令上花费太多时间,只要把 docker 和 docker-compose 安装好后,就直接找一两个 docker-compose 构建的开源项目来尝试,运行 docker-compose up 就可以了,这本来也就是使用 docker 后最大的好处之一,只需要一个命令,有 docker 镜像就启动服务,没有就相应地创建或下载,总之不用操心怎么安装环境什么的。
    • 另一个注意点是尽量选择那些以 alpine 为基础的镜像,文件占空间小。

以上只是心法,具体的知识和教程可参考下面的内容,网上也多得是:

参考链接

Windows 安装问题

在 Windows 系统安装经常会遇到各种各样的问题,Win10 系统如果是 Home 版或者遇到问题,无法使用 Docker-Desktop,就要考虑使用 Docker-Toolbox 了。

  • 首先要关闭 Hyper-V 后重启电脑,如果关闭后安装还出错,提示跟 Hyper-V,说明没关闭干净,参考 Windows 10 RS4 无法完全关闭Hyper-V导致Virtual Box 虚拟机 一文的方法,重点是下载工具并运行DG_Readiness_Tool_v3.4.ps1 -Disable
  • 其后安装 Docker-Toolbox 后,在命令行中运行 docker-machine create default 创建虚拟机。
  • 然后运行 docker images 看是否正常,如果出现类似这样的错误:
    error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/images/json: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.
    
  • 则需要执行 docker-machine env default 后根据提示执行: eval $("D:\docker\docker-machine.exe" env default) 即可。
  • 再次测试 docker-machine env default ,应该可以正常了。

配置本地库

国内镜像

基本概念

传统虚拟机:虚拟硬件和完整的操作系统,再运行应用; 容器:运行于宿主的内核,没有自己的内核,没有硬件虚拟。

Docker 包括三个基本概念,涉及 Docker 的整个生命周期。

  • 镜像(Image)[类]:由多层文件系统联合组成,支持容器运行和配置参数,无动态数据。
  • 容器(Container)[实例]:运行于独立命名空间的进程,以镜像为基础层,之上是容器存储层(会随容器消亡)。数据卷不会消亡。容器是拥有不同 IP 地址从而使其成为网络上可识别的独立 Linux 进程。容器依赖于镜像,如果想删除某个镜像,必须先删除相应的容器。
  • 仓库(Repository):Docker Registry => Repository => Tag == Image,“repository:tag”,一个镜像可以对应多个标签 tag。
  • 虚悬镜像(Dangling image):docker pulldocker build 导致标签指向新镜像,旧的无标签镜像变成虚悬镜像。
  • 黑箱镜像:使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像。
  • 数据卷:volume

Docker 网络

强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 –link 参数。

创建一个新的 Docker 网络

docker network create -d bridge my-net

docker 命令

使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。

docker主命令不要用后台运行,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出。正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

CMD ["nginx", "-g", "daemon off;"]

Docker run 详解

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  • 从地址池配置一个 ip 地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止

Docker Registry 公开服务

镜像服务被称为加速器。常见的有 阿里云加速器DaoCloud 加速器 等。

国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓库网易云镜像服务DaoCloud 镜像市场阿里云镜像库 等。

docker 编译一个 Dockerfile

docker build -t friendlyhello .

列出系统中的所有镜像:

docker images

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

删除所有虚悬镜像:

docker image prune

删除所有无主的数据卷:

docker volume prune

删除本地镜像:

docker image rm [选项] <镜像1> [<镜像2> ...]

# 删除所有仓库名为 redis 的镜像
docker image rm $(docker image ls -q redis)

# 删除所有在 mongo:3.2 之前的镜像
docker image rm $(docker image ls -q -f before=mongo:3.2)

查看镜像的历史记录

docker history ubuntu:latest

在某个端口映射下启动该镜像:

docker run -p 4000:80 friendlyhello
docker run -it --rm ubuntu:16.04 bash
  • -i:交互;
  • -t:终端;
  • –rm 容器退出后将其删除;
# 用 nginx 镜像启动一个容器,命名为 webserver,并且映射了 80 端口
docker run --name webserver -d -p 80:80 nginx

查看映射端口配置

docker port webserver

进入某个运行中的容器 bash

docker exec -it webserver bash

查看镜像、容器、数据卷所占用的空间

docker system df

列出系统中启动的容器:

docker container ls

CONTAINER ID        IMAGE               COMMAND             CREATED
1fa4ab2cf395        friendlyhello       "python app.py"     28 seconds ago

关闭某个容器:

docker container stop 1fa4ab2cf395

Services

docker stack ls                                            # List stacks or apps
docker stack deploy -c <composefile> <appname>  # Run the specified Compose file
docker service ls                 # List running services associated with an app
docker service ps <service>                  # List tasks associated with an app
docker inspect <task or container>                   # Inspect task or container
docker container ls -q                                      # List container IDs
docker stack rm <appname>                             # Tear down an application
docker swarm leave --force      # Take down a single node swarm from the manager

docker 命令帮助

Commands:
    attach    Attach to a running container                 # 当前 shell 下 attach 连接指定运行镜像
    build     Build an image from a Dockerfile              # 通过 Dockerfile 定制镜像
    commit    Create a new image from a container's changes # 提交当前容器为新的镜像
    cp        Copy files/folders from the containers filesystem to the host path
              # 从容器中拷贝指定文件或者目录到宿主机中
    create    Create a new container                        # 创建一个新的容器,同 run,但不启动容器
    diff      Inspect changes on a container's filesystem   # 查看 docker 容器变化
    events    Get real time events from the server          # 从 docker 服务获取容器实时事件
    exec      Run a command in an existing container        # 在已存在的容器上运行命令
    export    Stream the contents of a container as a tar archive   
              # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
    history   Show the history of an image                  # 展示一个镜像形成历史
    images    List images                                   # 列出系统当前镜像
    import    Create a new filesystem image from the contents of a tarball  
              # 从tar包中的内容创建一个新的文件系统映像[对应 export]
    info      Display system-wide information               # 显示系统相关信息
    inspect   Return low-level information on a container   # 查看容器详细信息
    kill      Kill a running container                      # kill 指定 docker 容器
    load      Load an image from a tar archive              # 从一个 tar 包中加载一个镜像[对应 save]
    login     Register or Login to the docker registry server   
              # 注册或者登陆一个 docker 源服务器
    logout    Log out from a Docker registry server         # 从当前 Docker registry 退出
    logs      Fetch the logs of a container                 # 输出当前容器日志信息
    port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
              # 查看映射端口对应的容器内部源端口
    pause     Pause all processes within a container        # 暂停容器
    ps        List containers                               # 列出容器列表
    pull      Pull an image or a repository from the docker registry server
              # 从docker镜像源服务器拉取指定镜像或者库镜像
    push      Push an image or a repository to the docker registry server
              # 推送指定镜像或者库镜像至docker源服务器
    restart   Restart a running container                   # 重启运行的容器
    rm        Remove one or more containers                 # 移除一个或者多个容器
    rmi       Remove one or more images
              # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
    run       Run a command in a new container
              # 创建一个新的容器并运行一个命令
    save      Save an image to a tar archive                # 保存一个镜像为一个 tar 包[对应 load]
    search    Search for an image on the Docker Hub         # 在 docker hub 中搜索镜像
    start     Start a stopped containers                    # 启动容器
    stop      Stop a running containers                     # 停止容器
    tag       Tag an image into a repository                # 给源中镜像打标签
    top       Lookup the running processes of a container   # 查看容器中运行的进程信息
    unpause   Unpause a paused container                    # 取消暂停容器
    version   Show the docker version information           # 查看 docker 版本号
    wait      Block until a container stops, then print its exit code   
              # 截取容器停止时的退出状态值

Docker 高级网络工具和示例

在介绍自定义网络拓扑之前,你可能会对一些外部工具和例子感兴趣:

pipework

Jérôme Petazzoni 编写了一个叫 pipework 的 shell 脚本,可以帮助用户在比较复杂的场景中完成容器的连接。

playground

Brandon Rhodes 创建了一个提供完整的 Docker 容器网络拓扑管理的 Python库,包括路由、NAT 防火墙;以及一些提供 HTTP, SMTP, POP, IMAP, Telnet, SSH, FTP 的服务器。

Docker 官方三剑客

Docker Compose 项目

  • 服务 (service):一个应用容器,实际上可以运行多个相同镜像的实例。
  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元。

Docker Machine 项目

在多种平台上快速安装 Docker 环境,在 macOS 上安装 xhyve 虚拟机支持:

brew install docker-machine-driver-xhyve

Docker Swarm mode 项目

提供 Docker 容器集群服务,具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。与 Kubernetes 是竞争关系。

使用方法:

初始化一个 Swarm 集群:
docker swarm init --advertise-addr 192.168.99.100

Swarm initialized: current node (7t2kqs1cmbw3r54921y9ofdcu) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-4l54p60fpaumw188uk5yea8l3z0sd80q6ydiav0e8r12w5cog1-8i70bpp0wtxggiemi2wx63f3g 192.168.99.100:2377

To add a manager to this swarm, run ‘docker swarm join-token manager’ and follow the instructions.

添加一个虚拟机后,加入此 swarm 遇到如下报错:
Error response from daemon: rpc error: code = Unavailable desc = grpc: the connection is unavailable

Kubernetes

Kubernetes 是 Google 团队发起的开源项目,它的目标是管理跨多个主机的容器,提供基本的部署,维护以及运用伸缩,主要实现语言为 Go 语言。

Kubernetes 实际上是一个希腊词κυβερνήτης,意思是”船的舵手”。 在这个意义上, Kubernetes 对于 Docker (集装箱船)倒是挺般配的。

OSv

OSv is the open source operating system designed for the cloud.

Moby

Moby defines the future in specialized container systems building. An open framework to assemble specialized container systems without reinventing the wheel.

似乎是更高、更深层定制化容器的工具,示例:LinuxKit

开源项目中几个文件各是什么意思?

  • Dockerfile 运行时的 docker 镜像生成文件,docker build . 并执行 docker run the-id-build 可尝试。
  • Capstanfile 是 OSv 的镜像生成文件。
  • Procfile 是 Heroku 的运行时命令文件。

问题解决

重启Docker主机

docker-machine restart default

docker-compose up 遇到 Windows named pipe error:(code: 2) 问题

docker-machine env

然后依照提示执行类似:

eval $("C:\Program Files\Docker Toolbox\docker-machine.exe" env)

再执行 docker-compose up 即可。