5分钟学docker

小TOT 创建于 2017-08-06

docker官网提供了丰富的文档让大家来学习docker,应该是我见过的写得做得最好的官方文档,毕竟专门有公司来维护。对于docker的学习,建议优先看官方文档,再google。官方文档地址

获取docker

docker官方提供了当今所有流行的操作系统的版本。详细见官方网站文档get docker。官方文档主要包含以下内容:

  • install Docker:该节主要介绍了docker的两个版本Docker CE,Docker EE 即社区企业版的差异,两个版本对不同操作系统(win,maos,linux)的支持情况,以及支持的云平台(Amazon,Azure)。同事也介绍了docker版本的发行策略。docker发行版主要分stable,edge版本,stable为稳定版提供更稳定的的支持,edge为抢先尝鲜版,提供最新的特性。
  • Docker EE详细介绍了企业版在不同操作系统的安装方法。
  • Docker CE详细介绍了社区版在不同操作系统的安装方法。

该章还提供了docker一些附加的介绍。详情查看官方文档。通过阅读这章,你能够清晰的知道,不同操作系统应该如何去安装docker。

简单使用docker

该章对应官方文档的Get started。简单的介绍了如何使用docker来运行我们的应用。算是对docker的一个最简单的应用。虽然例子简单,但是却涵盖了docker使用的各个阶段。完成这一章内容,你对docker的使用有一个简单的了解,使用docker完成的工作会让你无比兴奋,你会惊奇的发现,之前在日常运维遇到的环境部署,负载均衡,服务发现等棘手的问题在docker面前简直小菜一碟。docker带了一种全新的应用交付体验,应用的交付变得前所未有的简单。

Orientation(前言)

该章主要介绍了完成Get-started需要的环境准备,以及docker与虚拟机之间的区别,以及为什么要使用docker。简单的讲,这两种虚拟化技术,虚拟机属于重量级的解决方案,比较耗费资源,虚拟机模拟了完整的物理机。docker属于轻量级的解决方案,虚拟化过程中消耗的资源更少,这使得在一台机器上运行上千个虚拟环境变得可能,你无法想象一台宿主机上允许1000台virtal box虚拟机是什么场景,但使用docker在一台机器上运行1000个容器却非常容易。并且虚拟机完全模拟了物理机,他更适合模拟操作系统的环境,比较适合对虚拟环境要求比较高的场景,并不适合某个单一软件的运行环境。docker不仅仅能够模拟出程序的运行环境,还提供了容器间网络通信,容器内部数据目录挂载的支持,使得不同容器之间数据共享,网络通信变得更加容易。

虚拟机的架构图:

虚拟机架构图

docker的架构图: docker架构图

容器

什么是容器?简单的讲,将一根docker镜像运行起来,运行的实体就是容器,容器内部运行是我们的软件程序。把docker比喻成一艘船,容器就是docker上的集装箱,我们的程序就是集装箱中的货物。

docker镜像可以使用Dockerfile来定义,也可以在已有运行的容器提交更改来创建新的镜像。镜像需要告诉docker你运行的镜像需要的环境,例如目标程序网络,磁盘,运行环境,以及最终程序的运行方式。镜像有点类似虚拟机的镜像文件,但比虚拟机的镜像轻量很多,并且很好维护,docker镜像是分层的,不同的镜像可以共用基础层。这样不仅在下载的时候能够省去大量的流量,也方便管理。

下面是官方教程上的一份dockerfile

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

根据这个模板文件我们可以写一个简单的dockerfile,需要进一步了解dockerfile的书写,可以查询相关资料。

进入dockerfile所在目录,使用如下命令构建镜像

docker build -t friendlyhello:latest .

其中-t指明了镜像名称以及版本,版本号不填默认为latest。创建的镜像使用docker images命令查看。运行命令使用docker run [参数] (镜像tag|id)运行镜像。

镜像创建好了之后只能够本地使用,如果要讲镜像分享出去,或者在其他机器上使用,需要将镜像上传到镜像仓库,官方有个默认的镜像仓库docker hub,国内比较出名的镜像仓库有网易的蜂巢(可免费上传镜像),daocloud(需要开通企业版才能使用),阿里云。当然我们可以自己搭建镜像仓库registry ,官方有registry 的docker镜像,下载下来,运行即可完成搭建,非常的方便。

镜像如果不是提交到docker hub上,需要使用docker tag 命令将镜像重命名为对应仓库的镜像。在提交之前我们需要登录登录镜像仓库,我们可以使用docker login 镜像登录。登录之后就可以使用docker push命令将本地镜像推送到远程仓库。这是推送本地镜像到网易蜂巢的文档

备注

本节内容来源于官方文档的【容器】章节。除了以上常见的操作外,还有一些经验要分享。由于大部分的资源在国外,我们在下载镜像时速度往往不理想。给大家分享解决网络慢的经验。

  1. docker ce的下载可使用迅雷。
  2. 在下载镜像时可以使用daocloud的镜像仓库进行加速,或者直接使用国内镜像进行替换。加速配置文档
  3. 在我们没有条件搭建镜像仓库的时候,我们可以使用三方的镜像仓库。推荐使用网易蜂巢的镜像服务。

使用docker计算部署应用

在开发中,我们要运行镜像里面的程序。我们使用docker run imagetag命令。当我们放到正式环境时,我们常常需要解决应用负载均衡动态扩容,以及各个应用之间的依赖,以及故障重启等问题。有时候为了应对峰值流量,我们需要扩展我们的应用,添加更多的机器来提高服务,反之我们有时候为了节约服务器成本,我们需要减少我们的机器,避免资源浪费。docker为我们提供了弹性部署应用的方案。并且操作非常简单。

docker 应用集群的使用docker-compose.yml来定义。下面是一个简单的docker-compose.yml示例:

version: "3"
# 应用内的服务列表
services:
  #第一个服务,名字为web
  web:
    # 服务运行的镜像
    image: username/repo:tag

    ## 部署设置
    deploy:
      # 定义运行的实例个数
      replicas: 5
      # 服务重启策略:当服务停止就尝试重启
      restart_policy:
        condition: on-failure

      # 资源设置,这里设置了cpu,和内存资源限制
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
    ## 设置了服务的端口设置,这里将在容器内的8080端口绑定到宿主机的80端口上。
    ## 这样访问宿主机的80端口即访问服务的8080端口
    ports:
      - "80:8080"
    networks:
      - webnet

  # 这是第二个服务,服务名称叫visualizer,该服务被限定到只能够在swarm的manager节点上运行。
  # 该应用主要用于,监控整个swarm集群的运行状态。
  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - webnet
  # 这是第三个服务,服务名为redis,是一个redis数据库服务,用于集群其他服务数据存储。
  # 其他服务比如web链接该redis服务,可以使用“redis”作为数据库的host来链接redis这个服务
  # docker在运行整个负载均衡应用时已经将内部网络dns处理好,我们只需要使用服务名称即可得到目标容器再内部网络的ip
  redis:
    image: redis
    ports:
      - "6379:6379"
    volumes:
      - ./data:/data
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - webnet
networks:
  webnet:

通过以上docker-compose.yml文件,我们定义了一个负载均衡应用。该应用一共部署了3个服务,分别是web,visualizer,redis。这三个服务一起为外部提供服务。通过docker-compose.yml我们能够清晰的看到,整个集群的改如何运行。

有了docker-compose.yml我们只是定义好了集群应该怎样来运行,集群需要运行在swarm集群上。对于swarm我们可以将其看成是管理装有docker的机器(虚拟机、物理机)的工具。通过docker swarm init,docker swarm join。可以初始化一个swarm集群,以及将一台运行docker的机器加入到某个swarm集群。

docker swarm 网络拓扑图。 docker swarm

在swarm集群的manager节点运行docker stack deploy -c docker-compose.yml 应用名称来运行一个集群应用。运行后,使用docker stack ps 应用名称来查看集群的运行状态。这里出现了一个新的概念docker stack。前面我们提到docker swarm是用于docker 主机集群的管理,docker stack我们可以看成是docker容器管理工具。运行docker stack deploy -c docker-compose.yml 应用名称后,stack会在swarm集群中寻找合适的机器来运行整个应用中各个服务,如果没有特别的配置,各个服务运行在那台机器上是随机的,当然我们也可以使用配置一定的策略,比如各个机器均等分配,某个机器优先分配等,以及某个机器只有在资源紧张的情况下分配。

到这里,如果以上步骤顺利的话,我们就可以得到一个拥有负载均应用了,并且还支持动态伸缩。只要我们修改docker-compose.yml配置文件,并重新运行docker stack deploy命令即可。比如我们将上述的web服务的deploy:replicas的值改为3.重新运docker stack deploy命令,即可将集群中web服务的实例从5个变更为3个,以节省服务器资源。需要注意的是两次的应用名要一致。

后记

其实很久之前就有学习过docker,当时只接触了一些简单的容器创建工作。后面由于工作中没有再使用docker,很多东西只是有一个映像而已。这一次再次学习docker,按官方文档一步一步的操作,对docker有了进一步的认识。从docker与虚拟机的对比,docker image的创建,docker 的部署,docker swarm,docker stack一步步学习,对docker整个全貌有一个了解,知道应用如何搬到docker去运行。完成以上步骤,我们就能够使用docker来做点什么了。对于其他比较深入的知识点,比如如何去自定义网络,容器之间的通信,如何创存储镜像等,我们只需要去查阅官方文档或者google。写这一篇文章的目的在于希望记录一下在学习过程中的一些经验,也为大家提供一个入门的参考。该文章大部分的内容来源于官方文档的get-stated。如果你对docker不是很了解,并且希望尽快的入门,相信这是一篇很不错的入门文章。