9102 年了,学点 Docker 知识

栏目: 数据库 · 发布时间: 5年前

内容简介:最近工作需要,开发时需要用到 Docker。这篇文章从零开始演示几个 Demo,如果你之前没接触过 Docker,可以一步步跟着操作,加深对 docker 的理解。无论你所处的公司大或小,多多少少都遇到开发环境和生产环境不一致的问题。有些开发者用 Windows,有些开发者用 Mac,而生产环境可能用的是 Linux,同时跑着多个应用,每个应用依赖的 node 版本版本不一致,不同服务可能还占用相同的端口。于是我们常常听到这样的疑问:“本地明明是好的啊,为什么到线上就不行了?”(我自己的亲身经历:很早以前开

最近工作需要,开发时需要用到 Docker。这篇文章从零开始演示几个 Demo,如果你之前没接触过 Docker,可以一步步跟着操作,加深对 docker 的理解。

多图,请尽量在:computer:上观看

Docker 能解决什么问题

无论你所处的公司大或小,多多少少都遇到开发环境和生产环境不一致的问题。有些开发者用 Windows,有些开发者用 Mac,而生产环境可能用的是 Linux,同时跑着多个应用,每个应用依赖的 node 版本版本不一致,不同服务可能还占用相同的端口。于是我们常常听到这样的疑问:“本地明明是好的啊,为什么到线上就不行了?”

(我自己的亲身经历:很早以前开发前端项目,我需要在本地搭建 LEMP 环境,照着教程捣鼓好几天,一行前端代码都没有写。后来还因为一些“莫名其妙”的问题,反反复复重装了好几次。)

而使用了 Docker 之后呢,我们能通过配置文件一条命令快速构建环境,并且可以做到和其他服务隔离,互不影响,通过例子来讲解。

演示环境

这篇文章执行的环境是 macOS 10.14.1, Docker version 18.09.0

概念:镜像 vs 容器

镜像是以一些列历史操作叠加而成的,对镜像的每一次操作都会产生新的只读层,比方说你往容器写入内容,提交,再把它移除,则会产生两个历史只读层,有点像 git commits ,而容器可以理解问为镜像历史层 + 可写层的可运行系统,在可写层做任何操作都没问题,不提交的话,容器被删除后相应的改动也会丢失,有点像 git 暂存区

(个人理解,不一定对)

9102 年了,学点 Docker 知识

安装 Docker

Mac 安装 docker

brew cask install docker
复制代码

其他环境安装 Docker 查看这里。

安装完成之后,执行 hello-world 试一下。

$ docker run hello-world
复制代码
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
复制代码

这条命令会连接本地 Docker 服务,Docker 服务检测到本地没有 hello-world 镜像,于是去 Docker 镜像市场下载这个镜像,然后创建新的容器,运行特定的命令,输出 Hello from Docker!

这篇文章不讲解 docker 有哪些基础命令,直接从案例入手。

启动 nginx 服务

docker run -d -p 80:80 --restart=always  nginx:latest
复制代码

参数说明: run 启动某个镜像 -d 让容器在后台运行 -p 指定端口映射,宿主机的80端口映射到容器的80端口 --restart 重启模式,设置 always,每次启动 docker 都会启动 nginx 容器。

9102 年了,学点 Docker 知识

由于我本地没有 nginx:latest 的镜像,同样会先去镜像市场下载。启动完成打开http://localhost:80 就能立马看到 nginx 的欢迎页面。(对比以前,先在网上找教程,处理)

9102 年了,学点 Docker 知识

如果想修改欢迎页面,可以进入到容器内修改页面。

docker exec -it 4591552a4185 bash
复制代码

参数说明:

exec 对容器执行某些操作

-it 让容器可以接受标准输入并分配一个伪tty

4591552a4185 是刚刚启动的 nginx 容器唯一标记

bash 指定交互的程序为 bash

9102 年了,学点 Docker 知识

nginx 默认文件路径是 /usr/share/nginx/html/index.html ,直接用 echo 写入内容即可。

echo '<h1>Hello Docker<h1/>' > /usr/share/nginx/html/index.html
复制代码

ctrl + D 退出容器,重新访问 localhost:80 即可看到 Hello Docker。

9102 年了,学点 Docker 知识

每次修改内容都需要手动进入容器,太过繁琐,并且:point_up_2:提到了,对容器的直接修改不会持久保存,如果容器被删,数据也会跟着丢失。

(由于之前的 demo 已经占用了 80 端口,咱们先 kill 掉它。)

docker kill 4591552a4185
复制代码

Docker 提供数据挂载的功能,即可以指定容器内的某些路径映射到宿主机器上,修改命令,添加 -v 参数,启动新的容器。

docker run -d -p 80:80  -v ~/docker-demo/nginx-htmls:/usr/share/nginx/html/ --restart=always  nginx:latest
复制代码

启动成功之后,docker 会帮你生成目录 ~/docker-demo/nginx-htmls ,现在里面什么都没有,添加个 index.html。

9102 年了,学点 Docker 知识

再次打开 http://localhost:80 , 同样能看到 hello docker。

9102 年了,学点 Docker 知识

接着我们来用 Node + Redis + Docker 做一个 PV 展示的 DEMO。

运行命令:

docker run -d -p 6379:6379 -v ~/docker-demo/redis:/data redis:latest
复制代码

启动一个 redis 容器,并将数据持久化到 ~/docker-demo/redis 目录。(考虑性能,redis 并不会实时写入数据到磁盘)

用 koa 启动一个 node server,并连接 redis , 每次访问 / 都给计数器加一。

const Redis = require('ioredis');
const Koa = require('koa');
const Router = require('koa-router');

const router = new Router();
const app = new Koa();

const redis = new Redis(`redis://127.0.0.1:6379/0`);

router.get('/', async (ctx, next) => {
  await next();
  await redis.incr('pv');
  const current = await redis.get('pv');
  ctx.body = `current pv: ${current}`;
});
 
app
  .use(router.routes())
  .use(router.allowedMethods());

app.listen(3000);
复制代码

访问 http://localhost:3000 ,就能看到输出结果。

9102 年了,学点 Docker 知识

推荐使用 medis 可视化查看 redis 数据。

9102 年了,学点 Docker 知识

OK,开发环境完成功能开发,交付运维上线。我们假设生成环境会启动四个 node 服务,一个 redis 服务,和一个 nginx 做负载。

这时候需要把我们的 node 服务也构建成镜像,新增 dockerfile 文件。

# 基于最新的 node 镜像
FROM node:latest
# 复制当前目录下所有文件到目标镜像 /app/ 目录下
COPY . /app/
# 修改工作目录
WORKDIR /app/
# yarn 一下,安装依赖
RUN ["yarn"]
# 启动 node server
ENTRYPOINT ["node", "index.js"]
复制代码

更多 dockerfile 指令看这里

可以在本地构建一下,运行命令 docker build . --tag=pv ,然后通过 docker images 就能看到刚刚构建的新镜像。

继续往下走,编排一组容器,docker 官方提供了 docker-compose 工具。在项目目录下新增 docker-compose.yml 文件。

# 使用 docker-compose 2.2 版本
version: "2.2"
# 定义 services
services:
  redis:
    image: redis:latest
    volumes:
      - "~/docker-demo/pv/data/:/data/"

  web:
    # 放大4倍,也就会有四个 node server
    scale: 4
    build: .
    # 新增环境变量
    environment:
      - REDIS_HOST=redis://redis:6379/0
    # 依赖关系
    depends_on:
      - redis

  nginx:
    image: nginx:latest
    depends_on:
      - web
      - redis
    ports:
      - 80:80
    volumes:
      - "./default.conf:/etc/nginx/conf.d/default.conf"
复制代码

更多 docker-compsoe 指令看这里

service web 新增环境变量 REDIS_HOST=redis://redis:6379/0 是给 ioredis 链接用的,对应的要修改 js 文件。

const redis = new Redis(process.env.REDIS_HOST);
复制代码

redis://redis:6379/0 第一个 redis 是协议,第二个 redis 是 service host。service 之间可以通过 host 互相通信。

复制 nginx 容器下的 default.conf 文件出来修改

upstream web {
  server pv_web_1:3000;
  server pv_web_2:3000;
  server pv_web_3:3000;
  server pv_web_4:3000;
}

server {
    #...

    location / {
      proxy_pass http://web;
    }

    #...
}
复制代码

新增上游服务 web,这里的 pv 是我的项目文件名,web 是 docker-compose 文件中定义的 service name, 1 - 4 则是 scale 出来 docker 自动给定的序号。启动起来之后,nginx 访问 http://pv_web_1:3000 的请求就会到达第一个 web 容器。

万事具备,let's compose up!

9102 年了,学点 Docker 知识

好了,现在访问 http://localhost:80

9102 年了,学点 Docker 知识

到目前为止,我们已经把应用部署完成,每次访问 pv 数量自动加一,并且经过 nginx 负载均衡,会随机打到不同的容器上面。:tada::tada::tada:

总结

这篇文章演示了和前端相关的一些 docker 操作,从中我们可以看到其对于软件的开发,测试,部署都带来了极大的便利。文中的内容仅仅是冰山一角,更全面的学习可以看 Docker — 从入门到实践 这本书。

示例也只能作为学习使用,请不要直接用在生产环境。同时部分内容是个人理解,没有权威性,深入学习 Docker ,你应该去看详细的文档。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Designing for Emotion

Designing for Emotion

Aarron Walter / Happy Cog / 2011-10-18 / USD 18.00

Make your users fall in love with your site via the precepts packed into this brief, charming book by MailChimp user experience design lead Aarron Walter. From classic psychology to case studies, high......一起来看看 《Designing for Emotion》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器