[docker] 多容器项目

[docker] 多容器项目

相当于把之前学的一些东西全都整合一下,做一个小型的项目:

DB
Backend
Frontend

这里的数据库、前端、后端可以为任何框架,并不指定为特定框架

project structure

省略掉了一些实现,大概结构如下:

❯ tree
.
├── backend
│   ├── Dockerfile
│   ├── app.js
│   ├── logs
│   │   └── access.log
│   ├── models
│   │   └── goal.js
│   ├── node_modules
│   ├── package-lock.json
│   └── package.json
└── frontend
    ├── Dockerfile
    ├── README.md
    ├── package-lock.json
    ├── package.json
    ├── public
    └── src
        ├── App.js
        ├── components
        ├── index.css
        └── index.js

11 directories, 31 files

这里主要讲的是 Docker,所以代码部分不会涉及

创建网络

为 [docker] 网络连接 的内容

docker network create goals-net
e57f83cac82e93cdcbab09f515bb037c1990cafeaf77a3622a48059aace1d744

mongodb 容器化及持久化

为 [docker] 网络连接,[docker] 数据的持久化 - Volume & bind mounts 和 [docker] volume 补充 & 环境变量 & 参数 的内容

仅容器化

docker run -d --name mongodb --rm --network goals-net mongo
fc6ac2296a12b31a68b96fe7beb4f5a34a22c13c9f925b5242d8ab477f877920
❯ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                    NAMES
fc6ac2296a12   mongo        "docker-entrypoint.s…"   12 seconds ago   Up 11 seconds   27017/tcp                mongodb

这一部分的实现是起一个 mongodb 的容器,不存在任何的持久化和安全的实现

也就是说:

  • 任何人都可以访问当前 mongodb 实例
  • 一旦容器被删除,新的 mongodb 容器生成,那么数据就会消失

持久化数据

这里会使用 volume 去对数据进行一个持久化,这样新起来一个 mongodb 依旧会使用 volume 的数据

docker run -d --name mongodb --rm --network goals-net -v data:/data/db mongo
a376dd9549cc5cb1a45d74abcd8ae50fd838d8b730f6f278eecf9287fbc6da3c
❯ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                    NAMES
a376dd9549cc   mongo        "docker-entrypoint.s…"   3 seconds ago   Up 2 seconds   27017/tcp                mongodb
4ac01a93d3d3   goal-react   "docker-entrypoint.s…"   2 hours ago     Up 2 hours     0.0.0.0:3000->3000/tcp   goals-frontend
d4e6b80883e5   goal-node    "docker-entrypoint.s…"   2 hours ago     Up 2 hours     0.0.0.0:80->80/tcp       goals-backend

这里实现的功能室:

  • 数据不与 mongodb 容器的生命周期进行绑定

    只要容器使用 data 这个 volume,即可持久化数据

添加安全

这里的实现是根据 docerhub official mongo image 下的 security 部分添加:

docker run -d --name mongodb --rm --network goals-net -v data:/data/db -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=root mongo
6a3addfd1f2a0b8be89565eecc2e26a97c6e0a3917040505a4b64e10b7dfe325

⚠️:如果之前已经绑定过 named volume,那么需要重新删除该 volume,否则用户名密码可能无法重写 volume 中已经存在的默认数据

dockerize 后端

Dockerfile 如下:

FROM node

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 80

ENV MONGODB_USERNAME=root
ENV MONGODB_PASSWORD=root

CMD [ "npm", "start" ]

这里实现的就是比较基础的功能,就是 cv package.json,跑 npm install,cv 剩下的文件,暴露 80 端口,以及运行 npm start。这里之所以运行 npm start 而不是 node app.js 的原因是因为配置了 nodemon,这样可以让本机修改代码的时候,不用重新 rebuild/run docker 容器

这里来会 build 来回切换需要注意的一点就是,一定要确保自己在对应的目录下。打包后端就要在 backend 目录下,打包前端则要在 frontend 目录下

运行大致如下:

# make sure you are in backend projectdocker build -t goal-node .
# ignore building processdocker run --name goals-backend --rm -p 80:80 --network goals-net -d -v logs:/app/logs -v "$(pwd):/app" -v /app/node_modules goal-node
73662e085fc8cefd9e0a9b7c6d06d418559764b8419784809542fa4a4373282a
❯ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS         PORTS                    NAMES
73662e085fc8   goal-node    "docker-entrypoint.s…"   10 seconds ago   Up 8 seconds   0.0.0.0:80->80/tcp   goals-backend
fc6ac2296a12   mongo        "docker-entrypoint.s…"   2 minutes ago    Up 2 minutes   27017/tcp                mongodb

⚠️:这里暴露了 80 端口,因为前端项目最终还是通过浏览器实现,所以 docker 没有办法正确监听和 map 容器,因此最终前端还是需要通过浏览器访问 localhost

nodemon 是否成功运行可以通过修改一下代码,然后查看一下 log:

docker logs goals-backend

> backend@1.0.0 start
> nodemon app.js

[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node app.js`
CONNECTED TO MONGODB
❯ docker logs goals-backend

> backend@1.0.0 start
> nodemon app.js

[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node app.js`
CONNECTED TO MONGODB
[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
CONNECTED TO MONGODB!

修改代码肯定导致 log 变长,那就说明 nodemon 配置好了,同时也说明 bind mounts 成功了

env 使用补充

ENV 是可以在代码里被检测到的,所以这里也可以使用 process.env 去获取用户名和密码

mongoose.connect(
  `mongodb://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}@mongodb:27017/course-goals?authSource=admin`,
  {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  },
  (err) => {
    if (err) {
      console.error("FAILED TO CONNECT TO MONGODB");
      console.error(err);
    } else {
      console.log("CONNECTED TO MONGODB!");
      app.listen(80);
    }
  }
);

同样,也可以使用参数去重写环境变量,如在运行 docker run 时添加 -e MONGODB_USERNAME=root

dockerize 前端

Dockerfile 基本一致,除了不需要访问 mongodb,所以没有设置 ENV,以及暴露的端口不一样:

FROM node

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 3000

CMD [ "npm", "start" ]

关于前端的 HMR……这个基本取决于用什么脚手架和什么框架,如果是通过脚手架构建的项目,基本都是自带 HMR,不需要自行配置。同样,需要注意终端运行的地址,是前端所在的文件夹

# make sure you are in frontend projectdocker build -t goal-react .
# ignore the building processdocker run --name goals-frontend --rm -d -p 3000:3000 -it -v "$(pwd)/src:/app/src" goal-react
2e6f1d536066c45cf3b05cb456948c01009a23ddafdeb521cd8e4bcced2bb8a2
❯ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                    NAMES
4ac01a93d3d3   goal-react   "docker-entrypoint.s…"   2 seconds ago    Up 2 seconds    0.0.0.0:3000->3000/tcp   goals-frontend
d4e6b80883e5   goal-node    "docker-entrypoint.s…"   45 seconds ago   Up 45 seconds   0.0.0.0:80->80/tcp       goals-backend
fc6ac2296a12   mongo        "docker-entrypoint.s…"   16 minutes ago   Up 16 minutes   27017/tcp                mongodb

补充

补充一点说明信息

端口使用

如果查看一下端口,结果大概是这样的:

lsof -i :80

COMMAND    PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
Google    2410  user   37u  IPv6 0x51114bdb801afbef      0t0  TCP localhost:53403->localhost:http (CLOSE_WAIT)
com.docke 8888  user  277u  IPv6 0x51114bdb7e8fc3ef      0t0  TCP *:http (LISTEN)lsof -i :3000

COMMAND    PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
Google    2410  user   33u  IPv6 0x51114bdb7e9033ef      0t0  TCP localhost:53404->localhost:hbci (ESTABLISHED)
Google    2410  user   35u  IPv6 0x51114bdb7e9043ef      0t0  TCP localhost:53401->localhost:hbci (CLOSE_WAIT)
Google    2410  user   38u  IPv6 0x51114bdb7e18fbef      0t0  TCP localhost:53405->localhost:hbci (CLOSE_WAIT)
com.docke 8888  user  260u  IPv6 0x51114bdb7e195bef      0t0  TCP *:hbci (LISTEN)
com.docke 8888  user  287u  IPv6 0x51114bdb7e1903ef      0t0  TCP localhost:hbci->localhost:53404 (ESTABLISHED)lsof -i :27017

端口暴露

这里涉及到 docker 是怎么管理网络的,以上面的端口为例,可以看到 27017 是没有被暴露的,这个原因也很简单,容器虽然暴露了 27017,但是这只会被 docker 在对应的 network 进行管理,host machine 上自然没有办法检测到暴露的端口

也正是因为 docker 内部会对 network 进行管理,所以在后端项目可以直接使用容器名称去访问 mongodb,即这一段代码:

mongoose.connect(
  `mongodb://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}@mongodb:27017/course-goals?authSource=admin`
);

但是前端的代码是通过浏览器进行访问的,而浏览器所在的位置是 host machine,就像 host machine 不在 docker 管理的 network 上,无法访问到端口为 27017 的 mongodb 一样,浏览器也无法访问到在同一个 network 上的后端

假设如果现在这是一个微前端项目,每个前端模块都通过 docker 容器管理,那么模块与模块之间的引用——在不涉及到浏览器访问的情况下——是可以直接使用容器名称进行访问的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/570180.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年区块链链游即将迎来大爆发

随着区块链技术的不断发展和成熟,其应用领域也在不断扩展。其中,区块链链游(Blockchain Games)作为区块链技术在游戏行业中的应用,备受关注。2024年,区块链链游行业即将迎来爆发,这一趋势不容忽…

4款黑科技软件,其中三款功能过于强大,被误认为是外国佬开发的

国人对国产软件的刻板印象往往是“捆绑安装、弹窗广告、高昂收费”,这使得许多优秀的国产软件如同明珠蒙尘,鲜为人知。甚至有些软件的功能之强大,以至于常被人们误以为是出自外国佬开发,这实在是令人遗憾的事情。 1、VeryCapture…

docker快速搭建部署mqtt

文章目录 前言一、mqtt是什么?二、使用步骤1.引入库2.创建临时容器3.创建挂在目录4.将临时容器的配置挂载到宿主机中5.删除临时容器6.运行容器并挂载文件7.登录EMQX内置的管理控制台 总结 前言 一、mqtt是什么? MQTT(Message Queuing Teleme…

内容+货架“攻防一体”,京东能否上演“后来居上”?

又一家货架电商出手了。 2023年底,阿里进一步融合内容电商板块,合并淘宝直播与逛逛成立内容电商事业部,推动内容电商进入了新的阶段。近日,京东也开始发力视频赛道,宣布将拿出10亿现金、10亿流量补贴,全力…

C语言-结构体尺寸

CPU字长 字长的概念指的是处理器在一条指令中的数据处理能力,当然这个能力还需要搭配操作系统的设定,比如常见的32位系统、64位系统,指的是在此系统环境下,处理器一次存储处理的数据可以达32位或64位。 地址对齐 当计算机系统的…

Day 32 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

买卖股票的最佳时期Ⅱ 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意:你不能同时参与多笔交易(你…

RAKsmart洛杉矶大带宽服务器支持哪些操作系统?

RAKsmart洛杉矶大带宽服务器支持多种操作系统。具体包括以下几种,rak部落小编为您整理发布RAKsmart洛杉矶大带宽服务器支持哪些操作系统? RAKsmart作为一家提供海外服务器租用服务的公司,其洛杉矶大带宽服务器支持安装和运行多种操作系统。 这些操作系统…

WebServer项目介绍文章【四叶专属】

Linux项目实战C轻量级Web服务器源码分析TinyWebServer 书接上文,学习开源项目的笔记没想到居然有不少阅读量,后面结合另一个前端开源项目简单做了点修改,没想到居然有需要的同学,那么我就专门为四叶开一篇文章吧,【源码…

探索区块链世界:赋能创新,揭示区块链媒体发稿的影响力-世媒讯

区块链,这个由“区块”和“链”组成的概念,可能在您眼中充满神秘和复杂,但其实甚至无所不在,它正静悄悄地改变着我们日常生活的方方面面,从金融到媒体,从医疗到教育。 我们来揭开区块链的神秘面纱。区块链…

前端零代码开发实践:页面嵌套+逻辑连线0开发扩展组件,实现切换开关控制扇叶转动。能无代码封装扩展组件,有别于常规的web组态或低代码平台

前言: 官网:http://www.uiotos.net/ 什么是 UIOTOS? 这是一款拥有独创专利技术的前端零代码工具,专注于解决前端界面开发定制难题,原型即应用!具有页面嵌套、属性继承、节点连线等全新特性,学习门槛低…

AI 智能工具以及热门AI开源项目整理,包含国内中科院版GPT

AI 智能工具以及热门AI开源项目整理,包含国内中科院版GPT。 不用xx即可访问的镜像网站 https://chat1.yqcloud.top https://chat.bnu120.space https://chat.aidutu.cn https://hzdjs.cn/chatgpt https://chats.fenqubiao.com/zh 需要xx才能访问的网站 https://o…

金融时报:波场亮相哈佛大学并举办TRON Builder Tour活动

近日,波场TRON作为顶级白金赞助商出席哈佛区块链会议并成功举办TRON Builder Tour哈佛站活动,引发海外媒体热议。美联社、金融时报、Cointelegraph等国际主流媒体及加密知名媒体均对此给予了高度评价,认为本次大会对TRON Builder Tour活动具有里程碑意义,彰显了波场TRON致力于促…

spring security登录认证授权

spring security登录认证授权 是什么 Spring Security 主要实现了Authentication(认证,解决who are you? ) 和 Access Control(访问控制,也就是what are you allowed to do?,也称为Authorizat…

HTTP与SOCKS-哪种协议更适合您的代理需求?

网络代理技术是我们日常使用网络时必不可少的一项技术,它可以为我们提供隐私保护和负载均衡的能力,从而保证我们的网络通信更加安全和顺畅。而其中最主流的两种协议就是HTTP和SOCKS。虽然它们都是用于网络代理的协议,但在实际应用中却存在着一…

Java | Leetcode Java题解之第45题跳跃游戏II

题目&#xff1a; 题解&#xff1a; class Solution {public int jump(int[] nums) {int length nums.length;int end 0;int maxPosition 0; int steps 0;for (int i 0; i < length - 1; i) {maxPosition Math.max(maxPosition, i nums[i]); if (i end) {end maxP…

【网络安全】XSS漏洞注入,分类,防御方法

1.什么是XSS XSS全称&#xff08;Cross Site Scripting&#xff09;跨站脚本攻击&#xff0c;是最常见的Web应用程序安全漏洞之一&#xff0c;仅次于SQL注入。XSS是指攻击者在网页中嵌入客户端脚本&#xff0c;通常是JavaScript编写的危险代码&#xff0c;当用户使用浏览器浏览…

Linux——NFS网络文件系统

在生产环境中共享宿主目录可以用于集中管理账户 一、存储设备 DAS 是直连存储相当于移动硬盘 NAS 是网络文件系统&#xff0c;挂载后可以直接访问 SAN 存储区域网络 IPSAN 网线连接 共享的是设备&#xff0c;需要挂载后分区使用 FCSAN 光纤连接 二、服务的管理 1、安…

数据结构练习-线性表定义与基本操作

----------------------------------------------------------------------------------------------------------------------------- 1. 线性表是( )。 A.一个有限序列&#xff0c;可以为空 B. 一个有限序列&#xff0c;不可以为空 C. 一个无限序列&#xff0c;可以为空…

编译报错 - Missing trailing comma comma-dangle or Missing semicolon semi

一、comma-dangle规则&#xff1a; 这种错误通常出现在使用代码格式检查工具&#xff08;如ESLint&#xff09;时&#xff0c;具体是在JSON或者JavaScript对象、数组的最后一个元素后面缺少了逗号&#xff08;trailing comma&#xff09;。在某些编码标准中&#xff0c;要求在…

SS34B-ASEMI超低Low VF肖特基SS34B

编辑&#xff1a;ll SS34B-ASEMI超低Low VF肖特基SS34B 型号&#xff1a;SS34B 品牌&#xff1a;ASEMI 封装&#xff1a;SMB 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;3A 最大循环峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;40V 最大正向电压…
最新文章