首页 > 解决方案 > Docker-compose 与 nginx 反向,一个网站和一个宁静的 api?

问题描述

我希望你能帮我解决我的问题!这是信息。

情况

我目前有两个工作容器,我需要在同一个端口 80 上运行。有一个网站,目前只需转到服务器的主机 url 即可访问该网站,以及 restful api。但是,它必须通过端口 80 才能工作,并且登录会向 restful api 发出请求,该 api 也必须在端口 80 上侦听才能处理请求。因此,据我所知,我需要一个反向代理(例如 nginx)来适当地映射 interl/external 端口。

问题

当涉及到将 nginx 反向代理与其他两个容器一起 docker 化时,我真的不明白那里的教程......目前,restful api 使用一个简单的 Dockerfile,而应用程序使用 docker-compose 和一个 mysql 数据库。我非常不确定我应该如何做到这一点。我是否应该将所有这些都放在一个带有 nginx 反向代理的文件夹中,然后 docker-compose 处理所有子文件夹,每个子文件夹都有 dockerfiles/docker-compose?我看到的大多数教程都在谈论拥有两个不同的网站等,但似乎没有多少人在谈论一个 restful api 以及一个网站。据我了解,我肯定会使用这个 docker hub image

Docker 镜像当前结构

- RestApi
 - Dockerfile
  - main.go

- Website
 - Dockerfile
 - Docker-compose
 - Ruby app

我应该沿着反向代理文件夹创建一个父文件夹并将所有这 3 个放在父文件夹中吗?就像是 :

- Parentfolder
 - Reverse-proxy
 - RestApi
 - Website

然后有一些网站谈论修改启用站点的文件夹,一些不谈论,一些谈论虚拟主机,另一些谈论使用网络标签启动 docker ......我将把我的 nginx.conf 放在哪里?我会考虑在反向代理文件夹中安装它,但我不确定。老实说,我有点失落!以下是我当前的 dockerfile/docker-composes。

RestApi Dockerfile

FROM golang:1.14.4-alpine3.12

WORKDIR /go/src/go-restapi/

COPY ./testpackage testpackage/
COPY ./RestAPI .

RUN apk update
RUN apk add git

RUN go get -u github.com/dgrijalva/jwt-go
RUN go get -u github.com/go-sql-driver/mysql
RUN go get -u github.com/gorilla/context
RUN go get -u github.com/gorilla/mux

RUN go build -o main .

EXPOSE 12345

CMD ["./main"]

网站 Dockerfile

FROM ruby:2.7.1

RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update -qq && apt-get install -y bash nodejs tzdata netcat libpq-dev nano tzdata apt-transport-https yarn

RUN gem install bundler

RUN mkdir /myapp
WORKDIR /myapp

COPY package.json yarn.lock Gemfile* ./
RUN yarn install --check-files

RUN bundle install

COPY . .

# EXPOSE 3000

# Running the startup script before starting the server
ENTRYPOINT ["sh", "./config/docker/startup.sh"]

CMD ["rails", "server", "-b", "-p 3000" "0.0.0.0"]

网站 Docker-compose

version: '3'
services:
  db:
    image: mysql:latest
    restart: always
    command: --default-authentication-plugin=mysql_native_password
    # volumes:
      # - ./tmp/db:/var/lib/postgresql/data
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test_dev
      MYSQL_USERNAME: root
      MYSQL_PASSWORD: root

  web:
    build: .
    # command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    # volumes:
      # - .:/myapp
    ports:
      - "80:3000"
    depends_on:
      - db
    links: 
      - db
    environment: 
      DB_USER: root
      DB_NAME: test_dev
      DB_PASSWORD: root
      DB_HOST: db
      DB_PORT: 3306
      RAILS_ENV: development

我是否应该期望只“docker-compose up”一个图像,它将使用反向代理处理另外两个图像?如果有人能指出他们认为可以很好地解决我的问题的方法,我将不胜感激!任何被视为有用的教程也将不胜感激!我在谷歌上看过最多,他们似乎都跳过了一些步骤,但我对此很陌生,这让它有点难......

非常感谢!

新的 docker-compose.yml

version: '3.5'
services:
  frontend:
    image: 'test/webtest:first-test'
    depends_on:
      - db
    environment:
      DB_USER: root
      DB_NAME: test_dev
      DB_PASSWORD: root
      DB_HOST: db
      DB_PORT: 3306
      RAILS_ENV: development
    ports:
      - "3000:3000"
    networks:
      my-network-name:
        aliases:
          - frontend-name

  backend:
    depends_on:
      - db
    image: 'test/apitest:first-test'
    ports:
      - "12345:12345"
    networks:
      my-network-name:
        aliases:
          - backend-name      

  nginx-proxy:
    depends_on:
      - frontend
      - backend
    image: nginx:alpine
    volumes: 
      - $PWD/default.conf:/etc/nginx/conf.d/default.conf
    networks:
      my-network-name:
        aliases:
          - proxy-name
    ports:
      - 80:80
      - 443:443

  db:
    image: mysql:latest
    restart: always
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test_dev
      MYSQL_USERNAME: root
      MYSQL_PASSWORD: root
    ports:
      - '3306:3306'
    networks:
      my-network-name:
        aliases:
          - mysql-name
        
networks:
  my-network-name:

标签: dockernginxdocker-composedockerfilereverse-proxy

解决方案


我专门写了一篇关于使用 nginx 和 docker 进行反向代理的教程。

使用 Docker 创建 Nginx 反向代理

你基本上有 3 个容器和两个没有暴露端口的容器,它们将通过 docker 网络进行通信,并且每个都连接到网络。

重击方法:

docker create my-network;
# docker run -it -p 80:80 --network=my-network ...

或者

码头工人撰写方法:

文件: docker-compose.yml

version: '3'
services:
   backend:
      networks:
         - my-network
   ...
   frontend:
      networks:
         - my-network
   proxy:
      networks:
         - my-network
networks:
   my-network:
  • A - Nginx 容器代理 - MAPPED 80/80
  • B - REST API - 内部服务 80 - 给定名称backend
  • C - 网站 - 内部服务 80 - 给定名称frontend

在容器 A 中,您将只有一个 nginx conf 文件,该文件通过特定路由指向不同的服务:

文件: /etc/nginx/conf.d/default.conf

server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        proxy_pass http://frontend;
    }
    location /api {
        proxy_pass http://backend:5000/;
    }
    //...
}

这使得当您访问时:

如果您有任何问题,请告诉我,我已经构建了几次,甚至将 SSL 添加到代理容器中。

如果您要为本地开发测试一项服务,这很好,但对于生产(取决于您的托管服务提供商),这将是一个不同的故事,他们可能会使用自己的代理和负载均衡器自己管理它。


===================== 更新1:=====================

这是在 docker compose 中模拟后端、前端、代理和 mysql 容器。

在主项目目录中需要四个文件才能使其工作。

文件:

- backend.html
- frontend.html
- default.conf
- docker-compose.yml

文件: ./backend.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Backend API</title>
</head>
<body>
    <h1>Backend API</h1>
</body>
</html>

文件: ./frontend.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frontend / Website</title>
</head>
<body>
    <h1>Frontend / Website</h1>
</body>
</html>

配置代理 nginx 以指向网络上的正确容器。

文件: ./default.conf

# This is a default site configuration which will simply return 404, preventing
# chance access to any other virtualhost.

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Frontend
    location / {
        proxy_pass http://frontend-name; # same name as network alias
    }

    # Backend
    location /api {
        proxy_pass http://backend-name/;  # <--- note this has an extra /
    }

    # You may need this to prevent return 404 recursion.
    location = /404.html {
        internal;
    }
}

文件: ./docker-compose.yml

version: '3.5'
services:
    frontend:
        image: nginx:alpine
        volumes:
            - $PWD/frontend.html:/usr/share/nginx/html/index.html
        networks:
            my-network-name:
                aliases:
                    - frontend-name
    backend:
        depends_on:
            - mysql-database
        image: nginx:alpine
        volumes:
            - $PWD/backend.html:/usr/share/nginx/html/index.html
        networks:
            my-network-name:
                aliases:
                    - backend-name
    nginx-proxy:
        depends_on:
            - frontend
            - backend
        image: nginx:alpine
        volumes: 
            - $PWD/default.conf:/etc/nginx/conf.d/default.conf
        networks:
            my-network-name:
                aliases:
                    - proxy-name
        ports:
            - 1234:80
    mysql-database:
        image: mysql
        command: --default-authentication-plugin=mysql_native_password
        restart: always
        environment:
            MYSQL_DATABASE: 'root'
            MYSQL_ROOT_PASSWORD: 'secret'
        ports:
            - '3306:3306'
        networks:
            my-network-name:
                aliases:
                    - mysql-name
networks:
    my-network-name:

创建这些文件,然后运行:

docker-compose -d up;

然后访问:

  • 前端 - http://localhost:1234
  • 后端 - http://localhost:1234/api

您将看到两条路线现在都与它们各自的服务进行通信。您还可以看到前端和后端没有暴露端口。那是因为 nginx 在他们的默认端口 80 中,我们在我们的网络中给了他们别名my-network-name)来引用他们。

此外,我添加了一个 mysql 容器,该容器确实具有公开的端口,但您无法公开它们,只能让后端与主机通信:mysql-name在 port 上3306

如果您在开始使用 docker-compose 之前多了解一下该过程以了解事情的工作原理,我真的建议您查看上面链接中的教程。

希望这可以帮助。


===================== 更新2:====================

这是一个图表:

在此处输入图像描述


推荐阅读