Operations 10 min read

How to Deploy a Full‑Stack React & Express App with Docker‑Compose in One Command

This guide walks you through using Docker‑Compose to orchestrate a React front‑end, an Express back‑end, and a MariaDB database, covering environment setup, Dockerfile creation, Nginx configuration, container building, and common pitfalls for seamless full‑stack deployment.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
How to Deploy a Full‑Stack React & Express App with Docker‑Compose in One Command

Preface

Many open‑source projects are difficult to run locally because they require different environments and dependencies. Using docker compose up -d you can start a complete stack (backend, frontend, database) with a single command.

Prerequisites

Docker (installation includes docker‑compose)

A front‑end project (the example uses a React SPA)

A back‑end project (the example uses Express)

Ensure Docker is installed and running.

Front‑End Project Build

Create a React app with Create‑React‑App, adjust it for pre‑release or production environments, and add Axios for API calls. Then build the production assets: yarn build:prod The build folder contains the static files to be served.

Deploy the static files with Nginx inside a container:

docker run -d -p 80:80 -v /path/to/build:/usr/share/nginx/html --name frontend-test nginx

Replace the default Nginx configuration with a custom default.conf that correctly handles SPA routing.

server {
    listen 80;
    server_name localhost;
    root /home/frontend;
    location / {
        try_files $uri $uri/ @router;
        index index.html;
    }
    location @router {
        rewrite ^.*$ /index.html last;
    }
}

Build a Docker image for the front‑end:

FROM nginx
WORKDIR /home/frontend
COPY build .
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

Build and run the image:

docker build -t frontend .
docker run -d -p 80:80 --name frontend-v1 frontend

Database Setup

Start a MariaDB container (used instead of MySQL on M1 Macs):

docker run -p 3306:3306 --restart=always --privileged=true \
    --name mysql \
    -v /Users/user/Desktop/mysql/data:/var/lib/mysql \
    -v /Users/user/Desktop/mysql/my.cnf:/etc/mysql/my.cnf \
    -e MYSQL_ROOT_PASSWORD="123456" -d mariadb

Provide a custom my.cnf for character set and other settings.

Back‑End Project Start

Use an Express template, connect it to the database, and manage processes with pm2. Create pm2.config.js to define development and production environments:

module.exports = {
  apps: [{
    name: "myapp",
    script: "./bin/www",
    watch: true,
    env: { "NODE_ENV": "development" },
    env_production: { "NODE_ENV": "production" }
  }]
};

Start the appropriate environment:

pm2 start pm2.config.js --env development
pm2 start pm2.config.js --env production

Build a Docker image for the back‑end:

FROM keymetrics/pm2
RUN mkdir -p /home/backend
WORKDIR /home/backend
COPY ./ /home/backend
RUN yarn install
ENV NPM_CONFIG_LOGLEVEL warn
EXPOSE 9000
CMD ["pm2-runtime", "start", "pm2.config.js", "--env", "production"]

Build the image:

docker build -t backend .

docker‑compose.yml Configuration

Combine the three services (frontend, backend, mysql) into a single compose file, define a shared network, and set dependencies so containers start in the correct order:

version: '3'
networks:
  app-web:
    driver: bridge
services:
  mysql:
    image: mariadb
    ports:
      - 3306:3306
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    networks:
      - app-web
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_USER=root
      - MYSQL_ROOT_PASSWORD=123456
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
      - /etc/localtime:/etc/localtime
  backend:
    image: backend
    ports:
      - 9000:9000
    depends_on:
      - mysql
    networks:
      - app-web
  frontend:
    image: frontend
    ports:
      - 80:80
    depends_on:
      - backend
    networks:
      - app-web

Start and stop the stack:

docker compose up -d   # start all services
docker compose down    # stop and remove containers

Important Tips

Adjust MySQL host to mysql when containers cannot connect.

If image pull is slow, consider using a domestic mirror.

The front‑end and back‑end can be written in any language as long as they are containerized.

Use docker logs -f --tail 100 <containerId> to view logs.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DockerReactNginxExpressMariaDBFull‑Stack DeploymentDocker-Compose
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.