Home > OS >  Production Docker container hosting React shuts down
Production Docker container hosting React shuts down

Time:02-18

My dockerized react app is ready for deployment but shuts down after 10 or so seconds in the production environment. I have restart: unless-stopped in the docker-compose.prod.yml file which makes it restart every 10 or so seconds.

I have tried adding std_in: true and tty: true to the docker-compose.prod.yml file, as suggested, to no avail.

Docker Compose:

version: "3.8"

services:
  db:
    image: postgres:13-alpine
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./data:/var/lib/postgresql/data

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.prod
    image: "${BACKEND_IMAGE}"
    ports:
      - 8000:8000
    env_file: .env
    volumes:
      - static_volume:/backend/static
    restart: unless-stopped
    depends_on:
      - db

  # redis:
  #   image: redis:alpine
  #   restart: unless-stopped
  #   depends_on:
  #     - backend

  # celery:
  #   build:
  #     context: ./backend
  #   image: "${BACKEND_IMAGE}"
  #   command: celery -A backend worker -l info
  #   env_file: .env
  #   volumes:
  #     - ./backend/:/usr/src/app/
  #   restart: unless-stopped
  #   depends_on:
  #     - redis

  # celery-beat:
  #   build:
  #     context: ./backend
  #   image: "${BACKEND_IMAGE}"
  #   command: celery -A backend beat -l info
  #   env_file: .env
  #   volumes:
  #     - ./backend/:/usr/src/app/
  #   restart: unless-stopped
  #   depends_on:
  #     - redis

  frontend:
    image: "${FRONTEND_IMAGE}"
    stdin_open: true
    volumes:
      - frontend_build:/frontend/build
    restart: unless-stopped
    depends_on:
      - backend
    env_file: .env

  nginx:
    image: "${NGINX_IMAGE}"
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./nginx/certbot/conf:/etc/letsencrypt
      - ./nginx/certbot/www:/var/www/certbot
      - static_volume:/backend/static
      - frontend_build:/var/www/frontend
    restart: unless-stopped
    depends_on:
      - backend
      - frontend
      - db
    command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''

  certbot:
    image: certbot/certbot
    restart: unless-stopped
    volumes:
      - ./nginx/certbot/conf:/etc/letsencrypt
      - ./nginx/certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

volumes:
  frontend_build:
  static_volume:
  media_volume:

Dockerfile.prod:

FROM node:16.13.0

# Create and set the working directory on the container
# then copy over the package.json and package-lock.json
WORKDIR /frontend
COPY package*.json ./

# Install the node packages before copying the files
RUN npm install
COPY . .

# Run the production build
CMD ["npm", "run", "build"]

docker logs [frontend_container]:

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  npm install -g serve
  serve -s build

Find out more about deployment here:

  https://cra.link/deployment


> [email protected] build
> react-scripts build

Creating an optimized production build...

Thoughts on how to fix the issue? Could this be a permissions issue?

EDIT: I am serving with Nginx in a docker container:

upstream backend_server {
    server backend:8000;
}

server {
    listen 80;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location /api/ {
        return 301 https://$host$request_uri;
    }

    location /admin/ {
        return 301 https://$host$request_uri;
    }
    
    location /static/ {      
        return 301 https://$host$request_uri;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    root /var/www/frontend;
    server_name example.co www.example.co;

    ssl_certificate /etc/letsencrypt/live/exmplae.co/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.co/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location /api/ {
        proxy_pass http://backend_server$request_uri;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $https;
        proxy_connect_timeout 360s;
        proxy_read_timeout 360s;
    }

    location /admin/ {
        proxy_pass http://backend_server$request_uri;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $https;
        proxy_connect_timeout 360s;
        proxy_read_timeout 360s;
    }

    location /static/ {      
        alias /backend/static/;
    }

    location / {
        try_files $uri /index.html;
    }
}

CodePudding user response:

Once you have build your app, you should serve your app with a webserver like nginx. So, in your dockerfile add these lines to use an nginx docker image, copy your build into into and run it to the port 80.

FROM node:16.13.0

# Create and set the working directory on the container
# then copy over the package.json and package-lock.json
WORKDIR /frontend
COPY package*.json ./

# Install the node packages before copying the files
RUN npm install


# install react-scripts if needed
RUN npm install [email protected] -g --silent

COPY . .

# build your app
RUN npm run build

# production environment
FROM nginx:1.17.4-alpine
COPY --from=build /frontend/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
# change the left path with yours, below the file content
COPY src/nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

This is the nginx.conf:

server {

  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  error_page   500 502 503 504  /50x.html;

  location = /50x.html {
    root   /usr/share/nginx/html;
  }

}
  • Related