一般说来 SPA 的项目我们只要启一个静态文件 Server 就可以了,但是针对传统项目就不一样了,一个项目会依赖很多服务端程序。之前我们的开发模式是在一台开发机上部署开发环境,所有人都在这台开发机上使用 Samba 连接开发。老式开发是没什么问题的,但是前端因为引入了编译流程,增加了 Webpack 打包构建的行为,当多人共同开发的时候经常会因为内存爆满进程被杀导致打包失败。痛定思痛后为了解决这个问题,我决定将 Docker 引入我们的开发环境,通过将开发环境本地化来解决这个问题,所以有了本文。

本文内容主要是概括性,详情参照文尾链接1

也可参考视频链接2

Why Docker?

普通的 Web 服务一般都会依赖很多程序,例如 PHP, MySQL, Redis, Node 等等。正常情况下我们会去手动安装这些程序来配置服务需要的环境,这样会带来几个问题:

  1. 同一环境不同的服务依赖同一个软件的不同版本,经典的例如 python2 和 python3, 本地 Mac 上是 PHP7,但是服务只能支持 PHP5.6。

  2. 同一环境不同的服务可能会修改同一份文件,例如系统的配置,Nginx 的配置等,都会造成影响。

  3. 同一服务在多台机器上部署需要手工操作,导致大量的人力成本浪费。

这样逐个的安装软件实在是太麻烦了,所以大家就想干脆就直接把整个系统打包好放到机器上得了,于是就出现了虚拟机技术。这样做能保证系统环境的稳定以及重复的手工操作可以避免,但是也同样会带来一些问题:

  1. 打包后的虚拟机文件包含系统镜像所以特别大。

  2. 打包后的虚拟机文件包含系统镜像所以服务需要等待系统启动成功之后才能启动。

  3. 打包过程无法实现自动化。

针对第三点,后来出现了 Vagrant 使用 vagrantfile 的形式将镜像构建脚本化从而实现自动化的功能,不过其它两点没有解决。所以后来就出来了系统之上的进程级别虚拟化技术 —— Docker。它为我们带来了以下几个优点:

  1. 不需要打包系统进镜像所以体积非常小

  2. 不需要等待虚拟系统启动所以启动快速资源占用低

  3. 沙箱机制保证不同服务之间环境隔离

  4. Dockerfile 镜像构建机制让镜像打包部署自动化

  5. Docker hub 提供镜像平台方便共享镜像

以下是 VM 和 Docker 技术的具体区别,可以看到 VM 是打包了 Guest OS 进入镜像中的,而 Docker 是直接基于宿主系统虚拟化的实例。

Docker 基础

Docker 支持 Windows/Linux/Mac/AWS/Azure 多种平台的安装,其中 Windows 需要 Win10+,Mac 需要 EI Captain+。Docker 是一个 C/S 架构的服务,安装好 docker 之后需要启动 docker 软件后才能使用 docker 命令。

Docker 主要有 Dockerfile, Image, Container, Repository 四个基本概念。通过 Dockerfile 我们可以生成 Docker Image(镜像)。自己制作的镜像可以上传到 Docker hub 平台,也可以从平台上拉去我们需要的镜像。当镜像拉到本地之后,我们就可以实例化这个镜像形成一个 Container(实例) 了。一个简单的镜像启动的命令是:

$ docker run [组织名称]/<镜像名称>:[镜像标签]`

其中除了镜像名称,其它的都是可选参数。组织名称不填默认为library,镜像标签不填则默认为latest。例如经典的启动一个 Hello World 镜像的过程如下:

可以看到当我实例化hello-world这个镜像的时候,docker 发现本地没有这个镜像会先去 Docker hub 远端拉取镜像,如刚才说的,默认是latest标签。拉取后就会实例化执行入口命令了。我们除了可以使用 Docker hub 查找我们需要的镜像之外,也可以使用docker search命令来查找。16年的一篇文章显示,Docker hub 上的镜像包总量已经超过40万了,并且以每周4-5k的速度增长着。

下面我们就来看看如何运行一个 Nginx 容器实例:

    $ docker run

        -d

       --rm

       -p 8080:80 

       -v "$PWD/workspace":/var/www/hello.world

       -v "$PWD/hello.world.conf":/etc/nginx/conf.d/hello.world.conf

       nginx

使用docker run命令就能启动一个实例了,其中-p表示将本机的 8080 端口映射到镜像实例内的 80 端口,而-v表示将本地的$PWD/workspace文件夹映射到镜像实例里的/var/www/hello.world文件夹,后面的同理。最后再指定一下镜像名称,就能完成一次 Nginx 实例的启动了。此时访问http://hello.world:8080即可看到效果。

注:千万不要在容器实例中存储内容,实例销毁时实例内的所有内容都会被销毁,下次启动的时候又是全新的实例,内容不会保存下来。如果需要存储服务需要使用挂载卷或者外部存储服务。

Dockerfile

Dockerfile 是 Docker 比较重要的概念。它是 Docker 创建镜像的核心,它的出现给 Docker 提供了两大好处:

  1. 文本化的镜像生成操作让其方便版本管理和自动化部署

  2. 每条命令对应镜像的一层,细化操作后保证其可增量更新,复用镜像块,减小镜像体积

Dockerfile 的一些编写规则主要如下:

  1. 使用#来注释

  2. FROM 指令告诉 Docker 使用哪个镜像作为基础

  3. RUN 开头的指令会在创建中运行,比如安装一个软件包

  4. COPY 指令将文件复制进镜像中

  5. WORKDIR 指定工作目录

  6. CMD/ENTRYPOINT 容器启动执行命令

RUN 和 CMD/ENTRYPOINT 都是执行命令,区别在于 RUN 是在镜像构建过程中执行的,而 CMD/ENTRYPOINT 是在镜像生成实例的时候执行的,类似于 C/C++ 语言的头文件的正常代码的区别。而且后者在一个 Dockerfile 文件中只能有一个存在。CMD/ENTRYPOINT 的区别除了在写法上有区别之外,还有在docker run命令后增加 CMD 参数的情况下有区别(CMD会被复写)。一般建议使用 ENTRYPOINT 会更方便点。一个简单的 Node 命令行脚本的 Dockerfile 文件如下:

    FROM mhart/alpine-node:8.9.3 LABEL maintainer="lizheming <i@imnerd.org>" 

       org.label-schema.name="Drone Wechat Notification" 

       org.label-schema.vendor="lizheming" 

       org.label-schema.schema-version="1.1.0"

    WORKDIR /wechat

    COPY package.json /wechat/package.json

    RUN npm install --production --registry=https://registry.npm.taobao.org

    COPY index.js /wechat/index.js

    ENTRYPOINT [ "node", "/wechat/index.js" ]

这里我认为依赖是比较固定的,没有代码修改那么频繁,所以将其提前了。最终保证了所以越稳定的变化的命令至于上层,保证了每层打包出来的 Layer 能够尽可能的复用,而不会徒增镜像的大小。最后我们使用如下命令就可以完成一个 Docker 镜像的构建了:

$ docker build lizheming/drone-wechat:latest

参数和docker run是一样的。构建完成之后就可以开心的 push 到 Docker hub 上啦~

Docker Compose

以上我们说了下如何启动一个服务,但是我们都明白一个完整的项目肯定是不止依赖一个服务的,而 Docker 镜像的 ENTRYPOINT 只能设置一个,所以难道我们要使用docker run命令手动创建 N 个容器实例吗?为了解决这个问题,Docker Compose 就瞬时出现了。Docker Compose 是一款容器编排程序,使用 YAML 配置的形式将你需要启动的容器管理起来,免去我们需要多次执行docker run命令的烦恼。

Docker Compose 是使用 Python 开发的,它的安装非常的简单,直接pip install docker-compose就好了。安装完成之后分别使用up和stop命令可以启动和停止服务。一个简单的 docker-compose.yaml 配置文件大概如下:

    version: "2"

    services:

        nginx:

            depends_on:

              - "php"

            image: "nginx:latest"

            volumes:

              - "$PWD/src/docker/conf:/etc/nginx/conf.d"

              - "$PWD:/home/q/system/m_look_360_cn"

            ports:

              - "8082:80"

            container_name: "m.look.360.cn-nginx"

        php:

            image: "lizheming/php-fpm-yaf"

            volumes:

                - "$PWD:/home/q/system/m_look_360_cn"

            container_name: "m.look.360.cn-php"

Docker Compose 的另外一个好处就是能够帮我们处理容器的依赖关系,在每个容器中会将容器的 IP 和服务的名称使用 hosts 的方式绑定,这样我们就能在容器中直接使用服务名称来接入对应的容器了。例如下面这个 Nginx 配置中的php:9000就是利用了这个原理。

    server {

      listen 80;

      server_name dev.m.look.360.cn;

      charset utf-8;

      root /home/q/system/m_look_360_cn/public;

      index index.html index.htm index.php;

      error_page 500 502 503 504 /50x.html;

      location = /50x.html {

        root html;

      }

      # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000

      #

      location ~ .php$ {

        fastcgi_pass php:9000;

        #fastcgi_pass unix:/tmp/fcgi.sock;

        fastcgi_index index.php;

      }

    }

Docker 相关

基于 Docker 容器虚拟化技术除了以上说的解决部署环境之外,还有一些其它的优点,例如:

  1. 基于 Docker 的 CI 持续集成和 CD 持续支付

  2. 基于 Kubernetes, Docker Swarm 的集群弹性扩容和缩容

CI/CD 对于现在的敏捷开发是非常重要的,自动化任务帮助我们节省很多不必要的开发时间浪费,具体可查看链接。而 k8s 和 Docker Swarm 带来的弹性扩容和缩容让业务不在为流量问题而头疼。通过监控报警设置当出现峰值的时候自动扩容抗压,当出现低谷的时候自动去除多余的容器来节省成本,同时也将多余的资源给其它服务使用。

学习资料

  • 什么是 Docker ?https://cloud.tencent.com/developer/article/1005172

  • Docker 从入门到实践 https://yeasy.gitbooks.io/docker_practice/

  • Docker compose 详解 https://www.jianshu.com/p/2217cfed29d7

  • 深入浅出Docker https://www.kancloud.cn/infoq/docker/79768

文章中的链接

https://ppt.baomitu.com/d/025d62c6

http://cloud.live.360vcloud.net/theater/play?roomid=2321

https://medium.com/microscaling-systems/how-many-public-images-are-there-on-docker-hub-bcdd2f7d6100

https://imnerd.org/drone.html

Docker从入门到实践的更多相关文章

  1. Docker 从入门到实践(一)Docker 简介

    读前须知:本教程大部分都是[Docker 从入门到实践 ]一书的知识,有兴趣可以直接观看书籍.同时,借鉴书籍的知识,如有侵权,请告知我,我会删除处理.谢谢. 一.什么是 Docker? Docker ...

  2. 学习资源 Docker从入门到实践 pdf ,docker基础总结导图

    学习资源 Docker从入门到实践 pdf ,docker基础总结导图 Docker从入门到实践 pdf 云盘地址:https://pan.baidu.com/s/1vYyxlW8SSFSsMuKaI ...

  3. Docker从入门到实践(2)

    二.基本概念 Docker 镜像 我们都知道,操作系统分为内核和用户空间.对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持.而 Docker 镜像(Image),就相 ...

  4. Docker — 从入门到实践PDF下载(可复制版)

    0.9-rc2(2017-12-09)修订说明:本书内容将基于DockerCEv17.MM进行重新修订,计划2017年底发布0.9.0版本.旧版本(Docker1.13-)内容,请阅读docker-l ...

  5. 【转】Docker —— 从入门到实践

    http://yeasy.gitbooks.io/docker_practice/content/index.html Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud ...

  6. Docker 从入门到实践(二)Docker 三个基本概念

    一.Docker 的三个进本概念? 了解 Docker 的三个基本概念,就可以大致了解 Docker 的生命周期. 镜像(Image) 容器(Container) 仓库(Repository) 二.镜 ...

  7. Docker从入门到实践(1)

    一.Docker简介 1.1.什么是 Docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多 ...

  8. Docker从入门到实践(4-1)

    使用 Docker 镜像 在之前的介绍中,我们知道镜像是 Docker 的三大组件之一. Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像. ...

  9. Docker从入门到实践(3)

    三.安装 Docker Docker 分为 CE 和 EE 两大版本.CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月. Docker CE 分为  ...

随机推荐

  1. Web框架 - 开源软件库 - 开源中国社区

    网址:http://www.oschina.net/project/tag/127?lang=194

  2. POJ1704 Georgia and Bob Nim游戏

    POJ1704 这道题可以转化为经典的Nim游戏来解决. Nim游戏是这样的 有n堆石子,每堆各有ai个. 两个人轮流在任意石子堆中取至少1个石子,不能再取的输. 解决方法如下, 对N堆石子求异或 为 ...

  3. easyui 生成tas方式

    1.采用<a>标签形式 <div id="tabs" style="width:100%;"> <ul> <li id ...

  4. 关于mysql的索引原理与慢查询优化

    大多情况下我们都知道加索引能提高查询效率,但是应该如何加索引呢?索引的顺序如何呢? 大家看一下下面的sql语句(在没有看下面的优化的方法之前)应该如何优化加索引以及优化sql语句: 1.select  ...

  5. Centos7 配置防火墙 firewall

    一.firewall 1.从CentOS7开始,默认使用firewall来配置防火墙,没有安装iptables(旧版默认安装). 2.firewall的配置文件是以xml的格式,存储在 /usr/li ...

  6. Linux下 FACL详解

    1. 什么是ACL ACL即Access Control List 主要的目的是提供传统的owner,group,others的read,write,execute权限之外的具体权限设置 ACL可以针 ...

  7. P3043 [USACO12JAN]牛联盟Bovine Alliance(并查集)

    P3043 [USACO12JAN]牛联盟Bovine Alliance 题目描述 Bessie and her bovine pals from nearby farms have finally ...

  8. 乐搏讲自动化测试-Python发展背景(1)

    相信小伙伴们都知道,随着软件测试行业的发展和进步自动化测试已经成为必然.在竞争日益激烈的市场环境中也是你升职加薪的利器. 所以,小编决定从今天起!将要系统.连续.高质量的持续更新「整套自动化测试」文章 ...

  9. linux守护进程的编写

    linux监控一个进程进行 代码如下: #!/bin/sh cd /home/autoprocess/ auto=`pgrep -f autoProcessNew.php | wc -l` if [ ...

  10. ACM_三角形的周长

    三角形的周长 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n根棍子,棍子i的长度为ai,想要从中选出3根棍子组成周长尽可能长 ...