[docker] 网络连接

devtools/2024/9/25 10:31:39/

docker__0">[docker] 网络连接

使用 docker 容器会遇到下面 3 种情况:

  1. 容器与万维网之间的交流

    默认情况下是允许的

  2. 从容器到本机的交流

    假设有一些服务运行在本机,如数据库,而 docker 需要和本机进行交流去获取数据

    这个实现需要配置

  3. 容器与容器之间的交流

    这个是比较常见的用法了,同样需要配置

项目配置

配置一个 node 项目去运行一下项目

代码

app.js:

const express = require("express");
const bodyParser = require("body-parser");
const axios = require("axios").default;
const mongoose = require("mongoose");const Favorite = require("./models/favorite");const app = express();app.use(bodyParser.json());app.get("/favorites", async (req, res) => {const favorites = await Favorite.find();res.status(200).json({favorites: favorites,});
});app.post("/favorites", async (req, res) => {const favName = req.body.name;const favType = req.body.type;const favUrl = req.body.url;try {if (favType !== "movie" && favType !== "character") {throw new Error('"type" should be "movie" or "character"!');}const existingFav = await Favorite.findOne({ name: favName });if (existingFav) {throw new Error("Favorite exists already!");}} catch (error) {return res.status(500).json({ message: error.message });}const favorite = new Favorite({name: favName,type: favType,url: favUrl,});try {await favorite.save();res.status(201).json({ message: "Favorite saved!", favorite: favorite.toObject() });} catch (error) {res.status(500).json({ message: "Something went wrong." });}
});app.get("/movies", async (req, res) => {try {const response = await axios.get("https://swapi.dev/api/films");res.status(200).json({ movies: response.data });} catch (error) {res.status(500).json({ message: "Something went wrong." });}
});app.get("/people", async (req, res) => {try {const response = await axios.get("https://swapi.dev/api/people");res.status(200).json({ people: response.data });} catch (error) {res.status(500).json({ message: "Something went wrong." });}
});mongoose.connect("mongodb://localhost:27017/swfavorites",{ useNewUrlParser: true },(err) => {if (err) {console.log(err);} else {app.listen(3000);}}
);

下面这个是 mongoose 的配置:

const { Schema, model } = require("mongoose");const favoriteSchema = new Schema({type: String, // 'movie' | 'character'name: String,url: String,
});const Favorite = model("Favorite", favoriteSchema);module.exports = Favorite;

Dockerfile:

docker">FROM nodeWORKDIR /appCOPY package.json .RUN npm installCOPY . .CMD ["node", "app.js"]

简单解释一下这个代码就是,它会创立几个 endpoints,有两个 endpoints 会直接与进行沟通 https://swapi.dev/api/films,获取数据。还会有两个 endpoints 与 mongodb 进行沟通,进行 POST 和 GET 的 request

其中 https://swapi.dev/api/films 是一个 dummy API endpoint,是别人在网上 host 的:

在这里插入图片描述

而 mongodb 则是本机上进行安装,或者使用 docker 容器进行实现

下面会提一下怎么配置本机,但是这里只会运行容器与容器之间的沟通

docker_build_151">docker build

build 过程会报错:

docker build -t favorite-app .
[+] Building 7.3s (10/10)docker run --name favorites --rm -p 3000:3000 favorite-app
(node:1) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
(Use `node --trace-warnings ...` to show where the warning was created)
MongoNetworkError: failed to connect to server [localhost:27017] on first connect [Error: connect ECONNREFUSED 127.0.0.1:27017at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16) {name: 'MongoNetworkError'
}]at Pool.<anonymous> (/app/node_modules/mongodb/lib/core/topologies/server.js:441:11)at Pool.emit (node:events:519:28)at /app/node_modules/mongodb/lib/core/connection/pool.js:564:14at /app/node_modules/mongodb/lib/core/connection/pool.js:1000:11at /app/node_modules/mongodb/lib/core/connection/connect.js:32:7at callback (/app/node_modules/mongodb/lib/core/connection/connect.js:300:5)at Socket.<anonymous> (/app/node_modules/mongodb/lib/core/connection/connect.js:330:7)at Object.onceWrapper (node:events:634:26)at Socket.emit (node:events:519:28)at emitErrorNT (node:internal/streams/destroy:169:8)at emitErrorCloseNT (node:internal/streams/destroy:128:3)at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

出错的方式可能有两个:

  1. 本机没有安装 mongodb

  2. 安装了但是没有配置好

这里将 mongodb 连接的部分注释掉,重新运行一下:

在这里插入图片描述

发现 docker 容器和 https://swapi.dev/api/films 的交流沟通是没有任何问题的

运行 mongodb 镜像

这里运行一下结果就好了:

docker run -d --name mongodb mongo
# skip downloading process
Status: Downloaded newer image for mongo:latest
fb63b699a8ed81852c67057c3485ee4698be1437c3e6bef2bc3c87a1eca9a810

本机与容器交流

这里只要修改代码就好了:

mongoose.connect("mongodb://host.docker.internal:27017/swfavorites",{ useNewUrlParser: true },(err) => {if (err) {console.log(err);} else {app.listen(3000);}}
);

localhost 改成 host.docker.internal 即可

容器之间的沟通

这个有两种方法

直接沟通

第一个直接获取容器的 IP 地址:

# checked the exposed IP address by mongodocker container inspect mongodb | grep "IPAddress""SecondaryIPAddresses": null,"IPAddress": "172.17.0.2","IPAddress": "172.17.0.2",

然后更新代码:

mongoose.connect("mongodb://172.17.0.2:27017/swfavorites",{ useNewUrlParser: true },(err) => {if (err) {console.log(err);} else {app.listen(3000);}}
);

这个缺点在于每次重新运行容器的时候,IP 地址可能会出现改变,因此就需要修改代码,再重新 build

docker_networks_256">使用 docker networks

使用 network 可以让 docker 去管理 IP 地址,而非需要手动管理,这里第一步需要先通过 --network <network_name> 去创建一个 network

和 volume 不一样,docker 没有办法在容器运行的时候自动创建 network,所以先创建一个 network 是非常重要的事情

在 network 创建了之后,docker 会自动找寻连接在当前 network 上的容器并完成沟通

重新配置 mongo

如果在没有创建 network 的情况下直接运行 --network 就会报错:

docker run -d --rm --name mongodb --network favorites-net mongo
60cdc3029a12b8e6af46728ce648598fa987977df2e8bf9f729596436266c24b
docker: Error response from daemon: network favorites-net not found.

所以还是需要手动先创立一个 network:

docker network create favorites-net
f9385f787df37b608c6bc8bfb4619ff979c44312ee1f886965e17551dbde5d26
❯ docker network ls
NETWORK ID     NAME            DRIVER    SCOPE
624223e7a219   bridge          bridge    local
f9385f787df3   favorites-net   bridge    local
e0b7d35ecfa6   host            host      local
6592d848be44   none            null      localdocker run -d --rm --name mongodb --network favorites-net mongo
ac07e3660d2f04c515b7f635c37ae3e3e728f1c09c8afa9dfa0d64eb8e4cfe93
❯ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS       NAMES
ac07e3660d2f   mongo     "docker-entrypoint.s…"   11 seconds ago   Up 10 seconds   27017/tcp   mongodb
❯ docker container inspect mongodb | grep "net""NetworkMode": "favorites-net","SandboxKey": "/var/run/docker/netns/29cafc1c1f7a","favorites-net": {
更新 server 代码连接 network

这里的变化是把 ip 地址改成容器名称:

mongoose.connect("mongodb://mongodb:27017/swfavorites",{ useNewUrlParser: true },(err) => {if (err) {console.log(err);} else {app.listen(3000);}}
);

随后重新 build 和运行:

docker run --name favorites --rm --network favorites-net -p 3000:3000 favorite-app
(node:1) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
(Use `node --trace-warnings ...` to show where the warning was created)

最终可以完成 CRUD 的操作:

在这里插入图片描述

在这里插入图片描述


http://www.ppmy.cn/devtools/11421.html

相关文章

CentOS7下安装mysql8或者mysql5.7

mysql8 1、下载 访问mysql官网下载mysql8软件包 https://dev.mysql.com/downloads/mysql/ 选择相应的版本如&#xff1a;RPM Bundle mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar RPM Bundle 8.0.33 下载地址&#xff1a;https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.…

C#面:阐述什么是泛型委托

泛型委托是 C# 中一种强大的特性&#xff0c;它允许我们定义一个可以接受任意类型参数的委托。 通过泛型委托&#xff0c;我们可以在编写代码时不需要指定具体的参数类型&#xff0c;而是在使用委托时再指定参数类型。 在 C# 中&#xff0c;泛型委托的定义方式与普通委托类似…

虚拟化技术

什么是虚拟化 虚拟化&#xff1a;将应用程序和系统内核资源进行解耦&#xff0c;以操作系统级别进行隔离&#xff0c;目的是提高资源利用率 虚拟化架构 寄居架构 本机(真实的操作系统) ---> 虚拟化产品--->虚拟化操作系统或软件 源生架构 裸金属 服务器 --->虚拟…

​面试经典150题——从前序与中序遍历序列构造二叉树

​ 1. 题目描述 2. 题目分析与解析 二叉树的前序、中序和后序遍历 二叉树的前序、中序和后序遍历是树的三种基本遍历方式&#xff0c;它们是通过不同的顺序来访问树中的节点的。 前序遍历&#xff08;Pre-order traversal&#xff09;&#xff1a; 访问根节点 前序遍历左子树…

Day 31 贪心算法理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

贪心算法理论基础 ​ 贪心算法的本质&#xff1a;选择每一个阶段的局部最优&#xff0c;从而达到系统的整体最优&#xff1b; ​ 贪心的套路就是没有套路&#xff0c;最好的策略就是举反例&#xff0c;因为大多数时候并不要求严格证明&#xff0c;只需要得到普遍性结论即可&a…

手机号验证码登陆系统设计

设计一个手机号验证码登陆系统通常涉及以下几个关键步骤和组件&#xff1a; 1. 用户界面设计 前端部分 手机号输入框&#xff1a;用户输入其手机号码。 验证码输入框&#xff1a;用户输入接收到的短信验证码。 获取验证码按钮&#xff1a;用户点击后触发发送验证码请求。 …

安卓接收后台数据转模型int默认为double

问题&#xff1a;后台登录接口返回userid&#xff08;int整型10000&#xff09;&#xff0c;app前端&#xff08;使用okgo&#xff09;拿到userid&#xff08;double类型10000.0&#xff09;&#xff1b;导致app前端进行接下来操作如App中a用户使用userid转字符串后“10000.0”…

产教融合下的智慧养老实训室建设

智慧养老实训室开展产教融合&#xff0c;是指将职业教育与产业实践紧密结合&#xff0c;通过构建模拟真实工作环境的实训平台&#xff0c;让学生在校园内就能接触到最前沿的智慧养老技术与服务模式&#xff0c;同时&#xff0c;通过与养老行业的深度合作&#xff0c;确保人才培…