社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

9102 年了,学点 Docker 知识

运维 • 6 年前 • 772 次点击  
转载自掘金专栏,作者:DJI 前端开发工程师 HelKyle
链接:https://juejin.im/post/5c2c69cee51d450d9707236e
本文由 DJI 前端开发工程师 HelKyle(https://codepen.io/HelKyle/) 原创并分享于掘金

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

多图,请尽量在💻上观看

Docker 能解决什么问题

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

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

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

演示环境

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

概念:镜像 vs 容器

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

(个人理解,不一定对)

安装 Docker

Mac 安装 docker

brew cask install docker

其他环境安装 Docker 查看 这里(https://yeasy.gitbooks.io/docker_practice/install/)。

安装完成之后,执行 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 --80:80 --restart=always nginx:latest

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

由于我本地没有 nginx:latest 的镜像,同样会先去镜像市场下载。启动完成打开 http://localhost:80 就能立马看到 nginx 的欢迎页面。

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

docker exec -it 4591552a4185 bash

参数说明:
exec 对容器执行某些操作
-it 让容器可以接受标准输入并分配一个伪tty
4591552a4185 是刚刚启动的 nginx 容器唯一标记
bash 指定交互的程序为 bash

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

echo '

Hello Docker

> /usr/share/nginx/html/index.html

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

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

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

docker kill 4591552a4185

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

docker run --80:80 -~/docker-demo/nginx-htmls:/usr/share/nginx/html/ --restart=always nginx:latest

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

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

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

运行命令:

docker run --6379:6379 -~/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 ,就能看到输出结果。

推荐使用 medis(https://github.com/luin/medis/releases) 可视化查看 redis 数据。

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 指令看这里(https://yeasy.gitbooks.io/docker_practice/image/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 指令看这里(https://yeasy.gitbooks.io/docker_practice/image/dockerfile/)

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!

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

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

总结

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

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

相关文章

  • 官方文档:https://docs.docker.com/

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



●编号315,输入编号直达本文

●输入m获取文章目录

推荐↓↓↓

Linux学习

更多推荐25个技术类公众微信

涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、.NET、Linux、数据库、运维等。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/28901
 
772 次点击