nginx Docker Angular容器无法连接到Express服务器容器,即使两者位于同一网络中

r55awzrz  于 2023-08-03  发布在  Nginx
关注(0)|答案(1)|浏览(122)

我有一个angular应用程序运行在docker容器内的nginx服务器上,其基础镜像是nginx:stable-alpine,该容器的名称是“admin-users-cont”。这个docker容器存在于一个名为“tutorial-net”的docker网络中。我还有一个express服务器,它也运行在一个容器上,该容器的基础镜像是node:18.13.0,服务器的docker容器的名称是“server-cont”,express服务器容器也存在于同一个网络中,名为“tutorial-net”。服务器容器的IP地址是172.18.0.3,它在端口号3000上运行服务器。
server - index.js:

const express = require('express');
const bodyparser = require('body-parser');
const cors = require('cors');
const app = express();
const port = 3000;
const mysql = require('mysql2');

app.use(bodyparser.json());
app.use(cors());

const connection = mysql.createConnection({
    host: 'mysql-db-cont',
    port: '3306',
    user: 'root',
    password: 'password',
    database: 'docker-tutorial'
    // host: 'localhost',
    // port: '3307',
    // user: 'root',
    // password: 'password',
    // database: 'docker-tutorial'
});

connection.connect((err) => {
    if(err) {
        console.error("Error connecting to MySQL Database : " + err);
        return;
    }

    console.log('Connected to Database.');
});

app.get('/allprofiles', (req, res) => {
    
});

app.post('/adduser', (req, res) => {
    connection.query(`insert into \`docker-tutorial\`.\`Employee\` (\`first-name\`, \`last-name\`, \`email\`, \`company\`) values ('${req.body.firstname}', '${req.body.lastname}', '${req.body.email}', '${req.body.company}');`, (err) => {
        if(err) {
            res.json({"message": "Error while Inserting the record."}).status(500);
        }
        else {
            res.json({"message": "User inserted successfully."}).status(200);
        }
    });
});

app.get('/getusers', (req, res) => {
    console.log("Inside get users.");
    connection.query(`select \`first-name\`, \`last-name\`, \`email\`, \`company\` from \`docker-tutorial\`.\`Employee\`;`, (err, result) => {
        if(err) {
            console.log(err);
            res.json({"message": "Error while fetching the records."}).status(500);
        }
        else {
            console.log("Query Executed successfully\nResults : \n");
            console.log(result);
            res.json(result).status(200);
        }
    });
});

app.listen(port, () => {
    console.log("Listening on Port 3000");
});

function cleanup() {
    connection.end();
    console.log('Closing the Database connection.');
    process.exit(0);
}

process.on('SIGINT', cleanup)

字符串
向服务器发送get请求的angular list users组件是

import { Component } from "@angular/core"
import { UserService } from "../services/user.service";

@Component({
    selector: 'list-users',
    templateUrl: './list-users.component.html',
    styleUrls: ['./list-users.component.css']
})
export class ListUsersComponent {
    users: any;

    constructor(private userService: UserService) { }

    ngOnInit() {
        this.getUsers();
    }

    getUsers() {
        this.userService.getUsers().subscribe({
            next: (res) => {
                this.users = res;
            },
            error: (err) => {
                console.log("Some Error Occurred : ");
                console.error(err);
            },
            complete: () => {
                console.log("Response received - User added Successfully.");
            }
        });
    }
}


向后端请求的Angular 服务是:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class UserService {
    private backendUrl = "http://server-cont:3000";
    //private backendUrl = "http://localhost:3000";

    constructor(private http: HttpClient) { }

    addUser(userData: any) : Observable<any> {
        const url = `${this.backendUrl}/adduser`;
        return this.http.post<any>(url, userData);
    }

    getUsers() : Observable<any> {
        const url = `${this.backendUrl}/getusers`;
        return this.http.get(url);
    } 
}


现在nginx的配置文件是:

server {
    listen 80;
    sendfile on;
    server_name localhost;

    location / {
        root /usr/share/nginx/html/admin-users;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api {
        proxy_pass http://server-cont:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}


angular应用的docker文件是:

FROM nginx:stable-alpine

RUN ["rm", "/etc/nginx/conf.d/default.conf"]

COPY dist /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]


服务器应用的docker文件是:

FROM node:18.13.0

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]


我让用户创建docker容器和镜像的命令是:
Docker create angular application image:docker build -t admin-users .创建上述(admin-users)映像的容器:docker create -it --name admin-users-cont -p 8080:80 --network tutorial-net admin-users
Docker创建服务器应用镜像:docker build -t server .创建上述(服务器)映像的容器:docker create -it --name server-cont -p 3001:3000 --network tutorial-net server

tutorial-net是这两个容器(沿着mysql容器)所属网络的名称。

所有这些的问题是,我能够在浏览器上打开angular应用程序,但**/getusers**请求要么保持在挂起状态,要么在一段时间后失败,控制台中出现错误:GET http://server-cont:3000/getusers net::ERR_NAME_NOT_RESOLVED
请帮我解决这个问题,因为我已经被它卡住了10多天了。

4szc88ey

4szc88ey1#

server-cont主机名只有连接到tutorial-net网络的容器才知道。nginx服务器将/usr/share/nginx/html/admin-users文件夹中的内容按原样提供给浏览器。然后,Angular代码在浏览器中执行,浏览器可能不在Docker容器中运行,因此它不知道server-cont主机名。
要通过相同的nginx服务器(location /api块)访问API,您应该在Angular代码中使用相对URL或使用nginx服务器的URL作为基础URL。举例来说:

private backendUrl = "/api";

字符串

相关问题