• Docker极简入门:使用Docker-Compose 运行网站浏览量统计Demo


    Docker-Compose 是一个可以对 Docker 容器集群的快速编排的工具,能够减轻您心智和手指的负担。

    简单的来说 Docker-Compose 就是将你运行多个容器的命令编写到了一起,类似于你会为一系列重复操作写一个 doSomething.sh 文件,只不过 Docker-Compose 提供了更简便的语法。

    当然如果想管理多主机多容器还是推荐使用 k8s。

    我们的 demo 是一个基于 node.js 的网站服务,当用户访问当前服务器的根目录时,将 redis 中的浏览量计数增加1。

    先不看具体的业务代码,这其实无关紧要。假设我们已经写好了 node 服务,那么我们下一步就是写一个Dockerfile文件去构建镜像,然后执行 docker run 命令,这样整个服务就启动了。

    FROM node:18-alpine
    
    WORKDIR '/app'
    
    COPY package.json .
    RUN npm install
    COPY . .
    CMD ["npm","start"]
    

    这个Dockerfile 做的事情就是

    • 在容器中创建一个 app 目录,并切换到该目录。
    • 将宿主机当前目录下的 package.json 文件拷贝到容器中的当前目录(/app)下
    • 执行命令npm install
    • 将宿主机当前目录下的所有文件拷贝到容器中(因为主体程序index.js还没有拷贝到容器中)
    • 运行命令npm start启动服务

    因为我们的 node 服务用到了 redis,所以我们还需要启动一个 redis 容器。

    但 docker 的机制使得这两个容器是互相隔离的,所以想要通信的话

    • 将 redis 端口与宿主机端口做映射,通过宿主机的端口访问 redis
    • 创建 docker network,将两个容器放在同一个 docker network下
    • 编写 docker-compose.yml 文件,让Docker-Compose帮我们创建 docker network 搞定一切

    docker-compose.yml

    version: '3'
    services:
      ## 容器名
      redis-server: 
       ## 指定镜像
       image: 'redis:6.0.16-alpine'
       ## 容器重启策略
       restart: 'always'
      ## 容器名
      node-app:
       ## 当前目录执行 docker build
       build: .
       ## 端口映射
       ports: 
         - "8888:8081"
    

    虽然我们在文件中没有写任何有关 network 的代码,但 Docker-Compose会自动帮我们创建一个network

    运行命令

    sudo docker-compose up --build ## 会执行yaml文件中的build命令
    

    访问 localhost:8888 你应该能看到类似这样的界面

    docker-compose 的命令跟 docker类似

    docker-compose up -d ## 后台运行
    docker-compose down ## 停止
    

    最后是文件目录结构和 index.js 以及 package.json的具体代码

    .
    ├── docker-compose.yml
    ├── Dockerfile
    ├── index.js
    ├── package.json
    

    package.json

    {
        "dependencies": {
            "express": "^4.17.3",
            "redis": "^4.0.6"
        },
        "scripts": {
            "start": "node index.js"
        }
    }
    

    index.js

    const express = require('express');
    
    const redis = require('redis');
    
    const app = express();
    
    const client = redis.createClient({
      url : 'redis://redis-server:6379' // redis-server会被docker解析并转发
    });
    
    const db = {
      async set(key,value){
        return fun(async()=>{
          return await client.set(key,value)
        },key,value)
      },
      async get(key){
        return fun(async()=>{
          return await client.get(key)
        },key)
      }
    }
    
    async function fun(callback,key,value){
      return new Promise(async (res,rej)=>{
        await client.connect();
        let ok = callback(key,value);
        await client.quit();
        res(ok);
      })
    }
    
    db.set("visits",0);
    
    async function cntVisits(){
      let cnt = await db.get("visits");
      await db.set("visits",parseInt(cnt)+1);
      return parseInt(cnt)+1;
    }
    
    app.get('/', (req, res) => { 
        cntVisits().then( result => {
            res.send('Number of visits is ' + result); 
        });
    });
    // 8081是容器内部的端口,我们需要访问的是8888,因为在docker-compose.yml文件中已经做过端口映射了
    app.listen(8081, () => { console.log('Listening on port 8081'); });
    
  • 相关阅读:
    交比不变性证明
    小心这几个职场中容易触碰的规则
    2022牛客暑期多校训练营9(总结+补题)
    Laya:【音效BUG】在游戏失焦后再次返回游戏导致音效播放异常的问题与解决方案
    7-5 改写二分搜索算法
    TCP协议和UDP协议
    【数据库】事务
    [LeetCode]剑指 Offer 14- II. 剪绳子 II
    记录一次异常访问场景
    在 Java 中实现 Kafka Producer 的单例模式
  • 原文地址:https://www.cnblogs.com/AD-milk/p/16174417.html