• 容器化运维操作
  • psrheartache
  • #docker#moby
  • 2019-06-04
  • Wuhan,China
  • 1265
  • 7 min read

# 容器化运维操作

日趋复杂的运维开发环境,对虚拟服务器及应用服务的要求更加的多元化。我们需要更加容易扩展、性能优越、方便监控的管理服务,容器化应用、容器化运维应运而生。

【知己知彼】你将学习到:

  1. 理解/安装docker容器技术
  2. 秒级快速部署mysql、nginx、tomcat等服务
  3. 使用容器技术发布nodejs应用

【工欲善其事,必先利其器】你需要准备的环境(三选一):

  • Linux环境(Centos 7以上/Debian 8以上/Ubuntu 16.04LTS以上版本)
  • Windows 64位专业版/企业版/教育版(Build 15063以上)
  • macOS Sierra 10.12以上的版本

如果,你有了上面的环境,就可以很快速的跟着我们的内容快速学习。

# 容器和Docker

# 什么是容器化?

容器化是将应用程序或服务、其依赖项及其配置(抽象化为部署清单文件)一起打包为容器映像的一种软件开发方法。

docker-containerized-appliction-blue-border_2

软件容器充当软件部署的标准单元,其中可以包含不同的代码和依赖项。 按照这种方式容器化软件,开发人员和 IT 专业人员只需进行极少修改或不修改,即可将其部署到不同的环境。

容器化应用程序在容器主机上运行,而容器主机在 OS(Linux 或 Windows)上运行。因此,容器的占用比虚拟机 (VM) 映像小得多。

容器化的特点:

  • 一致的运行环境
  • 可伸缩性
  • 更方便的移植
  • 隔离性

# 什么是Docker?

Docker (opens new window)是用GO语言开发的应用容器引擎,基于容器化,沙箱机制的应用部署技术。可适用于自动化测试、打包,持续集成和发布应用程序等场景,包括阿里云,亚马逊在内的云计算服务商都采用了docker来打造serverless服务平台。它不仅仅可以部署项目,还可以用于数据库搭建,nginx服务搭建,nodejs、php等编程语言环境搭建。

PS: docker现已改名为moby

Docker中的三个重要概念

  • 镜像(image):分片的(只读)文件系统,由Dockerfile创建

    独立、易扩展、更效率

  • 容器(container):由Docker进程创建和管理的:文件系统 + 系统资源 + 网络配置 + 日志管理

    docker是docker镜像的运行环境,所以容器的概念就比较好理解了

  • 仓库(registry):用来远端存储docker镜像

    版本控制、变更管理、为持续集成与快速部署提供便利

# Docker vs 虚拟机

docker-containerized-and-vm-transparent-bg

  1. 容器是应用层的抽象,它将代码和依赖关系打包在一起。 多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器在用户空间中作为独立进程运行。 容器占用的空间比VM少(容器映像的大小通常为几十MB),可以处理更多的应用程序,并且需要更少的VM和操作系统。
  2. 虚拟机(VM)是物理硬件的抽象,将一台服务器转变为多台服务器。 管理程序允许多台VM在单台机器上运行。 每个VM都包含操作系统的完整副本,应用程序,必要的二进制文件和库 - 占用数十GB。 虚拟机也可能很慢启动。

总结一下:

特性 容器 虚拟机
启动 秒级 分钟级
硬盘使用 一般为 MB 一般为 GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个
开发/环境定制 方便(命令行、面向对象式) 进入虚拟机

相同点:

  1. 文件隔离/文件共享(沙箱)
  2. 资源隔离
  3. 网络隔离
  4. 支持多种宿主环境(扩展)
  5. 快照/镜像(版本控制/变更管理)

不同点:

  1. 不同的资源管理/依赖//释放(虚拟机占用更多的系统资源)
  2. 不同的应用运行环境
  3. Docker是写时复制
  4. 不同的日志方式(Docker收集日志,而虚拟机需要在虚拟系统里面看日志)
  5. 不同的交互方式(Docker偏shell,虚拟机偏GUI)

# Docker的工作原理(重点)

work

Docker是容器化部署技术,它主要作用在于通过运行容器来实现应用部署,而容器基于镜像运行。

简单地说,就是将你的项目和依赖包(基础镜像)打成一个带有启动指令的项目镜像,然后在服务器创建一个容器,让镜像在容器内运行,从而实现项目的部署。

服务器就是容器的宿主机,docker容器与宿主机之间是相互隔离的。

Docker 的基础是Linux容器(LXC:Linux Containers)等技术。

一般情况下:

Linux(服务器) -> tomcat安装 -> Java依赖 -> maven依赖 ->放置在/usr/lib目录 -> 配置tomcat端口/目录 -> 运行tomcat中的startup.sh脚本 -> 配置网络、防火墙等(后续) -> 服务启动

Docker:

使用基于java的tomcat镜像 -> docker run -> 指定端口/挂载webapp目录 -> 服务启动

这其中,发生了什么?

  1. Docker会自己拉取镜像,若本地已经存在该镜像,则不用到网上去拉取

  2. 创建新的容器

  3. 分配文件系统并且挂着一个可读写的层,任何修改容器的操作都会被记录在这个读写层上,你可以保存这些修改成新的镜像,也可以选择不保存,那么下次运行改镜像的时候所有修改操作都会被消除

  4. 分配网络\桥接接口,创建一个允许容器与本地主机通信的网络接口

  5. 设置ip地址,从池中寻找一个可用的ip地址附加到容器上,换句话说,localhost并不能访问到容器

  6. 运行你指定的程序

  7. 捕获并且提供应用输出,包括输入、输出、报错信息

Docker的价值:

从应用架构角度:统一复杂的构建环境;

从应用部署角度:解决依赖不同、构建麻烦的问题,结合自动化工具(如jenkins)提高效率。

从集群管理角度:规范的服务调度服务发现负载均衡

# 常见的应用场景介绍

Docker提供了轻量级的虚拟化,相比于虚拟机,可以在同一台机器上创建更多数量的容器。它常见的应用场景:1. 快速部署;2. 隔离应用; 3. 提高开发效率; 4. 版本控制; 5. 简化配置,整合资源;

# 快速部署

我们尝试着来部署一个mysql:

docker run -d --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 mysql
1

3

同样的道理,我们来部署一个nginx:

4

注意:这里没有映射服务端口,所以在80端口是看不到index.html中的内容的。需要加入-p参数来映射端口!!

docker run -d --name web -p 8000:80 -v ${your_dir}:/usr/share/nginx/html nginx
1

# 隔离应用

我们可以同时跑两个mysql,两个nginx,指定不同的端口进行映射:

mysql-test1映射到8001端口,把mysql-test2映射到8002端口。

docker run -d --name mysql-test1 -p 8001:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
docker run -d --name mysql-test2 -p 8002:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
1
2

把web1映射到8100端口,把web2映射到8200端口。

docker run -d --name web1 -p 8100:80 -v ${your_dir}:/usr/share/nginx/html nginx
docker run -d --name web2 -p 8200:80 -v ${your_dir}:/usr/share/nginx/html nginx
1
2

# 提高开发效率

  1. 一致的运行环境

    由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

  2. 更快速的启动时间

传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

  1. 更高效的复用系统资源

    由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。

  2. 仓库/镜像机制

    使用仓库可以方便的在任何有docker进程的虚拟机/服务器/主机上运行docker应用,环境的统一,让它们的部署变的非常的简单。

# 版本控制

Docker容器还可以像git仓库一样,可以让你提交变更到Docker镜像中并通过不同的版本来管理它们,来看看下面的例子:

我们之前创建了一个mysql,现在,我们使用commit命令就可以给它做一个快照,打上一个tag

5

在后面会详细的介绍Docker的常见命令

# DevOps流程

对开发和运维(DevOps (opens new window))人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。

使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile (opens new window) 来进行镜像构建,并结合 持续集成(Continuous Integration) (opens new window) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) (opens new window) 系统进行自动部署。

而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

# 使用Docker

# Docker如何进行安装

# 关于系统需求(重点)

  1. 平台类
操作系统 x86_64
Docker Desktop for Mac (macOS) (opens new window) yes
Docker Desktop for Windows (Microsoft Windows 10) (opens new window) yes
  1. 服务器
平台 x86_64 / amd64 ARM ARM64 / AARCH64 IBM Power (ppc64le) IBM Z (s390x)
CentOS (opens new window) yes (opens new window) yes (opens new window)
Debian (opens new window) yes (opens new window) yes (opens new window) yes (opens new window)
Fedora (opens new window) yes (opens new window) yes (opens new window)
Ubuntu (opens new window) yes (opens new window) yes (opens new window) yes (opens new window) yes (opens new window) yes (opens new window)

# Linux(重点)

对于中国用户:

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
1

对于国外vps:

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
1
2

脚本介绍:https://github.com/docker/docker-install

# Windows

安装Docker的系统需求:

  • 系统版本:Windows 10 64bit: Pro, Enterprise or Education (Build 15063 or later).
  • 在BIOS中开启了虚拟化(virtualization),正常情况下会默认开启,去系统管理中看看有没有Hyper-v被安装了。
  • CPU特性:SLAT-capable.
  • 4GB以上的内存

如果不满足上面的需求,则需要使用Docker Toolbox (opens new window),相当于是运行了一个virtualbox的虚拟镜像。

# MacOS

方法一官方dmg

官方下载地址:

Docker Descktop for Mac (opens new window)

对系统的要求:

Requires Apple Mac OS Sierra 10.12 or above. Download Docker Toolbox (opens new window) for previous OS versions.

只要系统是 Mac OS Sierra 10.12以上即可。

下载完Docker.dmg安装包之后,双击即可以安装,可能需要系统管理员权限,输入密码即可。

运行过后,小图标:

安装完之后,在终端工具中,使用docker version来查看Docker版本。

方法二brew cask:

brew update 

brew cask install docker

# 删除的方法, 还需要手动删除Docker.app
brew cask uninstall docker
1
2
3
4
5
6

上面的命令将会把Docker安装在Applications目录下。

# Docker国内加速

  1. Docker的Toolbox镜像站(推荐),主要是针对低版本的windows与mac用户:

http://mirrors.aliyun.com/docker-toolbox/ (opens new window)

  1. Docker镜像加速,主要是对docker pull拉取镜像操作进行网络加速优化:

需要注册阿里云的账号,登录容器Hub服务 (opens new window),在左侧的加速器帮助页面就会显示为你独立分配的加速地址。

image-20190524172015448

# 第一个Docker应用hello world

  1. 查看docker版本

  2. 运行第一个Docker应用

    使用docker run命令

  3. 查看容器运行状态

    使用docker ps命令来查看正在运行的容器的状态,-a参数来查看所有的已经运行的容器(无论是否停止)

1

# Docker常见命令(重点)

  • 创建run-p 映射宿主机的端口给镜像服务使用,-v 挂载宿主机的文件目录到镜像里面去,-it是提供交互式的终端工具,-d 是让镜像容器在后台去持续运行,--name 指定容器的名称,exec可以进入到容器里面去:

    docker exec -it <container_name> /bin/bash
    
    docker exec -it <container_name> /bin/sh
    
    1
    2
    3
  • 启动start/停止stop/重启restart/删除已停止容器rm

  • 登录仓库login/拉取镜像pull/推送push/提交镜像commit/给指定容器标签tag

    docker hub上去注册我们的账号,才能使用login

    使用docker commit来给运行中的容器打tag:

    docker commit <container_id> <namespace>/<image_name>:tag
    
    1
    docker commit e12b80defe8c demo/mysql
    
    1

    使用pull/push命令来推送本地的镜像到远程仓库

    docker pull/push <namespace>/<image_name>:tag
    
    1
  • 查看所有本地镜像images/删除本地镜像rmi

    删除镜像之前,要停止stop并且删除rm运行中的容器。

  • 查看容器服务打印的日志logs/检阅容器inspect(更详细的容器信息,硬件/网络/版本等)/进入容器exec

  • 查看版本version/docker进程信息info

  • 查看命令帮助:

docker <run/pull> --help
1

# 扩展知识

# 制作Docker镜像(重点)

Dockerfile 是一个由一堆命令+参数构成的脚本,使用 docker build 即可执行脚本构建镜像,自动的去做一些事,主要用于进行持续集成。

一般,Dockerfile 共包括四部分:

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令

当Node.js遇见Docker,下面介绍Docker在前端中的应用:

一个简单的Koa应用:

const Koa = require('koa');
const app = new Koa();

// response
app.use(ctx => {
  ctx.body = 'Hello Koa!!';
});

app.listen(3000);
1
2
3
4
5
6
7
8
9

Dockerfile示例:

FROM node:10

LABEL maintainer=demo@demo.cn

# 创建 app 目录
WORKDIR /app

# 把 package.json,package-lock.json(npm@5+) 或 yarn.lock 复制到工作目录(相对路径)
COPY ["package.json","*.lock","./"]

# 打包 app 源码
# 特别注意:要指定工作目录中的文件名
COPY src ./src

# 使用.dockerignore文件,上面两个COPY合并成一个
# COPY . .

# 使用Yarn安装 app 依赖
# 如果你需要构建生产环境下的代码,请使用:
# --prod参数
RUN yarn --prod --registry=https://registry.npm.taobao.org

# 对外暴露端口 -p 4000:3000
EXPOSE 3000

CMD [ "node", "src/index.js" ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

使用docker build打包:

docker build -t ${your_name}/${image_name}:${tag} .
1

这里的your_name代表的是远程仓库中的用户名,或者仓库地址; image_name为镜像名称,tag是给镜像打的标签,用于版本控制。例如:

docker build -t demo/node-demo:1.0 .
1

打包过程:

$ docker build -t demo/node-demo:1.0 .
Sending build context to Docker daemon  17.92kB
Step 1/8 : FROM node:10
 ---> 5a401340b79f
Step 2/8 : LABEL maintainer=demo@demo.cn
 ---> Using cache
 ---> dd01419f30d5
Step 3/8 : WORKDIR /app
 ---> Using cache
 ---> bb9a44851ec9
Step 4/8 : COPY . .
 ---> Using cache
 ---> b08ff37c5456
Step 5/8 : RUN ls -la /app
 ---> Using cache
 ---> 4e0e57e807a1
Step 6/8 : RUN yarn --prod --registry=https://registry.npm.taobao.org
 ---> Using cache
 ---> 96ab842b4766
Step 7/8 : EXPOSE 3000
 ---> Using cache
 ---> 505dda4e680f
Step 8/8 : CMD [ "node", "src/index.js" ]
 ---> Using cache
 ---> f60e25a577de
Successfully built f60e25a577de
Successfully tagged demo/node-demo:1.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

回顾前面的知识:

如何使用?

还记得docker run命令吗?

docker run -d --name nodedemo -p 3000:3000 demo/node-demo:1.0
1

然后使用docker ps来看运行状态

$ docker run -d --name nodedemo -p 3000:3000 demo/node-demo:1.0
c863da9afea1558593843233aec08989184d8dafbb0f8443830d1e523104ab00
$ docker ps
CONTAINER ID        IMAGE                   COMMAND               CREATED             STATUS              PORTS                    NAMES
c863da9afea1        demo/node-demo:1.0   "node src/index.js"   2 seconds ago       Up 1 second         0.0.0.0:3000->3000/tcp   nodedemo
1
2
3
4
5

# Docker-compose介绍

通过 Docker-Compose 用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。

docker-compose

Compose 中有两个重要的概念:

  • 服务 (service) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目 (project) :由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Docker Compose 是 Docker 的独立产品,因此需要安装 Docker 之后在单独安装 Docker Compose .

安装方法:

#下载
sudo curl -L https://github.com/docker/compose/releases/download/1.20.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
#安装
chmod +x /usr/local/bin/docker-compose
#查看版本
docker-compose --version
1
2
3
4
5
6

常见使用:

前面的例子,使用docker-compose改写:

version: '3'
services:
  mysql:
    image: mysql
    container_name: test-mysql
    ports:
    - "8000:3306"
    environment:
    - MYSQL_ROOT_PASSWORD=123456
1
2
3
4
5
6
7
8
9

在此文件的当前目录下,使用docker-compose up -d来执行。

生命周期管理:

创建:run/up

启动/停止/删除/重启:start/stop/rm/restart

检视/日志:logs/ps

看两个个复杂的应用:

搭建本地mongo + mongo-express服务

version: '3.1'
services:
  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: 123456
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

给公司搭建一个git服务器吧?!

项目地址: https://github.com/sameersbn/docker-gitlab

推荐服务器配置:适用于10人的小团队~~~~

2core

2GB+2GB(swap)

version: '2'

services:
  redis:
    restart: always
    image: sameersbn/redis:4.0.9-1
    command:
    - --loglevel warning
    volumes:
    - /srv/docker/gitlab/redis:/var/lib/redis:Z

  postgresql:
    restart: always
    image: sameersbn/postgresql:10
    volumes:
    - /srv/docker/gitlab/postgresql:/var/lib/postgresql:Z
    environment:
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production
    - DB_EXTENSION=pg_trgm

  gitlab:
    restart: always
    image: sameersbn/gitlab:11.11.0
    depends_on:
    - redis
    - postgresql
    ports:
    - "10080:80"
    - "10022:22"
    volumes:
    - /srv/docker/gitlab/gitlab:/home/git/data:Z
    environment:
    - DEBUG=false

    - DB_ADAPTER=postgresql
    - DB_HOST=postgresql
    - DB_PORT=5432
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production

    - REDIS_HOST=redis
    - REDIS_PORT=6379

    - TZ=Asia/Kolkata
    - GITLAB_TIMEZONE=Kolkata

    - GITLAB_HTTPS=false
    - SSL_SELF_SIGNED=false

    - GITLAB_HOST=localhost
    - GITLAB_PORT=10080
    - GITLAB_SSH_PORT=10022
    - GITLAB_RELATIVE_URL_ROOT=
    - GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphanumeric-string
    - GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
    - GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alphanumeric-string

    - GITLAB_ROOT_PASSWORD=123456
    - GITLAB_ROOT_EMAIL=demo@demo.cn
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

docker-compose在前端里面的使用:

Nodejs + mongodb + koa + vue的应用组合:

特别注意:

视频中,我们使用vue是在局部安装的,所以使用npx命令在进行创建。

vue官网推荐大家进行全局安装:

npm i -g @vue/cli

# 然后使用
vue create myproject
1
2
3
4

docker-compose.yml

version: '3'
services:
  web:
    image: web:1.0
    ports:
    - "8080:80"

  server:
    image: server:1.0
    ports:
    - "3000:3000"
    depends_on:
    - mongodb
    links:
    - mongodb:db

  mongodb:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

depends_on 决定了容器加载的先后顺序,这里mongdbweb先加载,mongdb创建完成之后,再来创建server

# 自学补充知识

  1. 什么是Kubernetes?

Kubernetes, 中文意思是舵手或导航员,它是一个容器集群管理系统,主要职责是容器编排(Container Orchestration)——启动容器,自动化部署、扩展和管理容器应用,还有回收容器。

文档: https://kubernetes.io/zh/

集群相关:Mesos (opens new window)Docker Swarm (opens new window)

  1. 简单的DevOps流程介绍:

devOps

参考链接:从一张图看Devops全流程 (opens new window)

  1. Docker中的文件系统,深入理解原理:

一图看尽Docker容器文件系统

  1. Docker的一般开发流程介绍:

    • 寻找基础镜像
    • 基于基础镜像编写Dockerfile脚本
    • 根据Dockerfile脚本创建项目镜像
    • 将创建的镜像推送到docker仓库 (根据自身需要,可做可不做)
    • 基于项目镜像创建并运行docker容器 (实现最终部署)

    这里面如果一扩展,就变成了自动化开发流程,比如:加入版本控制git -> 使用webhook -> jenkins自动打包 -> docker自动构建 -> 推送镜像 -> 生产环境部署

# 资源

Docker for Mac【系统:10.12以上】: https://download.docker.com/mac/stable/Docker.dmg

Docker for Windows【系统:专业版及企业版】: https://download.docker.com/win/stable/Docker%20for%20Windows%20Installer.exe

Docker ToolBox for Mac【系统:10.10.3以上】: https://download.docker.com/mac/stable/DockerToolbox.pkg

Docker ToolBox for Windows【系统:windows7以上】:https://download.docker.com/win/stable/DockerToolbox.exe