首页 > 解决方案 > 无法在 MacOS 上的 Dockerized React Web 应用程序中连接到前端

问题描述

我最近受雇于一个网站开发项目,但在 MacOS 上通过 docker 部署它时遇到了麻烦。我只是无法通过 localhost:8000 连接到前端。我已经通过在虚拟机(Ubuntu)中运行 docker 暂时解决了这个问题,但是由于这种连接,有些事情无法正常工作。

有哪些方法可以解决这个问题?

这是 dockerfiles 中的配置:

Dockerfile(前端)

# pull official base image
FROM node:12-alpine as build


# create and set working directory
WORKDIR /app
# install app dependencies
RUN mkdir frontend
COPY package.json ./frontend/
COPY package-lock.json ./frontend/
COPY frontend_healthchecker.sh ./frontend/
RUN chmod +x /app/frontend/frontend_healthchecker.sh

RUN ls
RUN cd frontend && ls
RUN cd frontend && npm install --only=prod
# RUN cd frontend && npm install --scripts-prepend-node-path=auto

# add app code
COPY . ./frontend/
RUN cd frontend && ls

# start app
RUN cd frontend && npm install && npm run build

FROM nginx:1.16.0-alpine
COPY --from=build /app/frontend/build /usr/share/nginx/html
COPY --from=build /app/frontend/nginx/default.conf /etc/nginx/conf.d/default.conf

COPY --from=build /app/frontend/frontend_healthchecker.sh /home
RUN chmod +x /home/frontend_healthchecker.sh
RUN apk add curl
RUN apk search curl
HEALTHCHECK CMD ["/bin/sh", "/home/frontend_healthchecker.sh"]

EXPOSE  8000

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

Dockerfile(后端)

FROM node:12
ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

#install ffmpeg
RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get install -y ffmpeg
RUN apt-get install -y mediainfo

RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get install -y python-pip
RUN pip --version
RUN pip install numpy
RUN pip install opencv-contrib-python
RUN pip install urllib3

WORKDIR /app

COPY . /app
COPY backend_healthchecker.sh /app
RUN chmod +x backend_healthchecker.sh

RUN ls
RUN npm install

EXPOSE 8080

WORKDIR /app/bin

HEALTHCHECK CMD ../backend_healthchecker.sh
ENTRYPOINT ["node"]

CMD ["www"]

docker-compose.yaml

version: '3.3'
services:
    kurento:
        network_mode: "host"
        build:
            context: ./kurento
        volumes: 
            - "/etc/timezone:/etc/timezone:ro"
            - "/etc/localtime:/etc/localtime:ro"
            - static-content:/tmp
        container_name: p_kurento
        environment:
            - GST_DEBUG=2,Kurento*:5
    mongo:
        network_mode: "host"
        image: mongo:latest
        restart: always
        container_name: p_mongo
        volumes: 
            - "/etc/timezone:/etc/timezone:ro"
            - "/etc/localtime:/etc/localtime:ro"
            - db-content:/data/db
        healthcheck:
            test: mongo localhost:27017/test | mongo show dbs
            interval: 1m
            timeout: 15m
            retries: 5
    backend:
        network_mode: "host"
        env_file:
            - ./backend/.env
        build:
            context: ./backend
        container_name: p_backend
        volumes: 
            - "/etc/timezone:/etc/timezone:ro"
            - "/etc/localtime:/etc/localtime:ro"
            - static-content:/files
    frontend:
        network_mode: "host"
        env_file:
            - ./frontend/.env
        build:
            context: ./frontend
        container_name: p_frontend
        volumes: 
            - "/etc/timezone:/etc/timezone:ro"
            - "/etc/localtime:/etc/localtime:ro"
    coturn:
        network_mode: "host"
        build:
            context: ./stun
        container_name: p_turn

    portainer:
        #network_mode: "host"
        restart: always
        image: portainer/portainer
        command: --admin-password=somepassword -H unix:///var/run/docker.sock
        ports:
            - "9000:9000"
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
        container_name: portainer

volumes:
  static-content:
  db-content:

标签: reactjsmacosdockerlocalhost

解决方案


network_mode: host不适用于 MacOS 或 Windows 系统。Docker使用主机网络文档说明:

主机网络驱动程序仅适用于 Linux 主机,不支持 Docker Desktop for Mac、Docker Desktop for Windows 或 Docker EE for Windows Server。

它还基本上完全禁用了 Docker 的网络堆栈,并且几乎从不需要。

你需要在这里做三件事:

  1. network_mode: host从 Compose 文件中删除所有行。(这些container_name:线条也是不必要的。)
  2. 对于您需要从 Docker 外部访问的任何服务(可以是所有服务,这很好),添加ports:以发布其容器端口。
  3. 当这些服务中的任何一个在内部调用其他服务时,配置它们的 URL(例如,在.env文件中)以使用它们的 Compose 服务名称。(请参阅Docker 文档中的Compose中的网络。)(另请注意,您的前端应用程序可能实际上在浏览器中运行,即使代码是从容器提供的,并且根本不能使用这些主机名;这一点需要仍然使用localhost或最终部署系统的主机名。)

因此,例如,前端和后端容器的设置可能如下所示:

version: '3.8'
services:
  mongo: { ... }
  backend:
    # no network_mode: host or container_name:
    # if this needs to be accessed from the browser application
    ports:
      - '8080:8080'
    # probably actually put this in .env
    environment:
      - MONGO_HOST=mongo
    # unchanged from the original
    env_file:
      - ./backend/.env
    build:
      context: ./backend
    volumes: 
      - "/etc/timezone:/etc/timezone:ro"
      - "/etc/localtime:/etc/localtime:ro"
      - static-content:/files
  frontend:
    ports:
      - '8000:8000'
    environment:
      - BACKEND_URL=http://localhost:8080 # as would be seen from the browser
    env_file:
      - ./frontend/.env
    build:
      context: ./frontend
    volumes: 
      - "/etc/timezone:/etc/timezone:ro"
      - "/etc/localtime:/etc/localtime:ro"

推荐阅读