@yarnstart
Превозмогание и React

Запуск frontend сборки в контейнере docker?

Контейнер с nginx отдаёт статику, отдельно стоит контейнер с нодой, на нём запускается фронтенд с hot-reload на порту 8081. У контейнера с нодой expose 8081. Этот же порт я связываю nginx ports - '8081:8081'.
docker-compose.yml

version: '3.2'

networks:
  backend-network:
    driver: bridge
  frontend-network:
    driver: bridge

volumes:
  redis-data:
  pg-data:
  home-dir:

services:
  &app-service app: &app-service-template
    build:
      context: ./docker/app
      dockerfile: Dockerfile
    user: '${USER_ID:-1000}:${GROUP_ID:-1000}'
    volumes:
    - /etc/passwd:/etc/passwd:ro
    - /etc/group:/etc/group:ro
    - ./src:/app:rw
    - home-dir:/home/user
    hostname: *app-service
    environment:
      REDIS_HOST: redis
      REDIS_PORT: &redis-port 6379
      DB_HOST: postgres
      DB_PORT: &pg-port 5432
      DB_DATABASE: &pg-db-name app
      DB_USERNAME: &pg-username forge
      DB_PASSWORD: &pg-password secret
      SCHEDULE_PERIOD: 60
      FPM_PORT: &php-fpm-port 9000
      FPM_USER: '${USER_ID:-1000}'
      FPM_GROUP: '${GROUP_ID:-1000}'
      APP_ENV: local
      APP_DEBUG: 'true'
      HOME: /home/user
    command: keep-alive.sh
    depends_on:
    - redis
    - postgres
    networks:
    - backend-network

  &queue-service queue:
    <<: *app-service-template
    restart: always
    hostname: *queue-service
    command: php /app/artisan queue:work

  &scheduler-service scheduler:
    <<: *app-service-template
    restart: always
    hostname: *scheduler-service
    command: scheduler.sh 'php /app/artisan schedule:run'

  &php-fpm-service php-fpm:
    <<: *app-service-template
    user: 'root:root'
    restart: always
    hostname: *php-fpm-service
    ports: [*php-fpm-port]
    entrypoint: /fpm-entrypoint.sh
    command: php-fpm --nodaemonize -d 'opcache.enable=0' -d 'display_startup_errors=On' -d 'display_errors=On' -d 'error_reporting=E_ALL'
    networks:
    - backend-network
    - frontend-network

  &node-service node:
    image: 'node:alpine'
    working_dir: /app
    hostname: *node-service
    volumes:
      - ./src:/app
    expose:
      - '8081'

  nginx:
    build:
      context: ./docker/nginx
      dockerfile: Dockerfile
    restart: always
    working_dir: /usr/share/nginx/html
    environment:
      FPM_HOST: *php-fpm-service
      FPM_PORT: *php-fpm-port
      ROOT_DIR: '/app/public' # App path must equals with php-fpm container path
    volumes:
    - ./src:/app:ro
    ports:
      - '9999:80'
      - '8081:8081'
    depends_on:
    - *php-fpm-service
    networks:
    - frontend-network

  redis:
    image: redis:4.0.11-alpine
    restart: always
    command: redis-server
    volumes:
    - redis-data:/data:rw
    ports: [*redis-port, '16379:6379'] # Port 16379 for connecting from localhost
    networks:
    - backend-network

  postgres:
    image: postgres:9.6.10-alpine
    restart: always
    environment:
      POSTGRES_DB: *pg-db-name
      POSTGRES_USER: *pg-username
      POSTGRES_PASSWORD: *pg-password
    volumes:
    - pg-data:/var/lib/postgresql/data:rw
    ports: [*pg-port, '15432:5432'] # Port 15432 for connecting from localhost using, for example, data-grip
    networks:
    - backend-network


Запущенный webpack-dev-server с hot-loader

ℹ 「wds」: Project is running at https://localhost:8081/
ℹ 「wds」: webpack output is served from https://localhost:8081/


webpack.config.js

const path = require('path');
// variables
const isProduction = process.argv.indexOf('production') >= 0;
const sourcePath = path.join(__dirname, './resources');
const outPath = path.join(__dirname, './public');
const hostPort = 8081;
// plugins
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
  context: sourcePath,
  entry: {
    main: ['./app.tsx'],
  },
  optimization: {
    minimizer: isProduction ? [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})] : [],
  },
  output: {
    path: outPath,
    filename: 'js/app.js',
    chunkFilename: '[chunkhash].js',
    publicPath: isProduction ? '/' : `https://localhost:${hostPort}/`,
  },
  target: 'web',
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx'],
    // Fix webpack's default behavior to not load packages with jsnext:main module
    // (jsnext:main directs not usually distributable es6 format, but es6 sources)
    mainFields: ['module', 'browser', 'main'],
    alias: {
      app: path.resolve(__dirname, 'resources/'),
      components: path.resolve(__dirname, 'resources/components/'),
      types: path.resolve(__dirname, 'resources/types/'),
      'react-dom': '@hot-loader/react-dom',
    },
  },
  module: {
    rules: [
      {
        test: [/\.tsx?$/, /\.ts?$/],
        use: [
          {
            loader: 'awesome-typescript-loader',
            options: {
              useCache: true,
              useBabel: true,
              babelOptions: {
                babelrc: true,
              },
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader', 'sass-loader'],
        }),
      },
      { test: [/\.png$/, /\.svg$/], use: 'url-loader?limit=10000' },
      { test: /\.jpg$/, use: 'file-loader' },
    ],
  },
  plugins: [
    new WebpackCleanupPlugin({
      exclude: ['.htaccess', 'favicon.ico', 'index.php', 'robots.txt'],
    }),
    new ExtractTextPlugin({
      filename: 'css/app.css',
      disable: !isProduction,
    }),
    new BundleAnalyzerPlugin({
      analyzerMode: (isProduction ? 'server' : 'disabled'),
    }),
  ],
  devServer: {
    contentBase: sourcePath,
    hot: true,
    inline: true,
    host: 'localhost',
    port: hostPort,
    https: true,
    headers: { 'Access-Control-Allow-Origin': '*' },
    watchOptions: {
      exclude: [/node_modules/],
    },
    historyApiFallback: {
      disableDotRule: true,
    },
    stats: 'minimal',
  },
  devtool: 'cheap-module-eval-source-map',
  node: {
    fs: 'empty',
    net: 'empty',
  },
};


Открываю страницу по localhost:9999, на нём подключается скрипт, получаю ошибку
GET https://localhost:8081/js/app.js net::ERR_CONNECTION_RESET

Сначала думал на вебпак и https, но при запуске webpack сборки локально - всё работает.
P.S. Новичок в работе с докером, за основу взят https://gitlab.com/tarampampam/laravel-in-docker, буду рад ссылкам в нужном направлении.
  • Вопрос задан
  • 413 просмотров
Пригласить эксперта
Ответы на вопрос 1
@vitaly_il1
DevOps Consulting
Посмотрите логи контейнеров.

Плюс, насколько понимаю, для nginx не надо (нельзя) маппировать 8081 - это порт ноды.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы