john_ryan
john_ryan

Reputation: 1787

"Create React App" with Docker

I was wondering if anyone had any experience using create-react-app with docker. I was able to get it set up with a Dockerfile like:

from node
RUN mkdir /src
WORKDIR /src
ADD package.json /src/package.json
RUN npm install
EXPOSE  3000
CMD [ "npm", "start" ]

And then used a docker-compose file like:

app:
  volumes:
    - "./app:/src"
  ports:
    - "3000:3000"
    - "35729:35729"
  build: ./app

This allowed me to start up the container and view the app. However livereload didn't work when saving files in the mounted volume and webpack created several .json.gzip files in the src directory.

Any suggestions for getting this working correctly?

Upvotes: 16

Views: 29588

Answers (7)

oceanBT
oceanBT

Reputation: 204

Here is a simple (pure docker) solution without local installation of runtime (e.g. node):

cd /tmp
docker run -it --rm -v "$PWD":/app -w /app node  yarn create react-app my-app
sudo chown -R $USER:root my-app/
cd my-app
nano docker-compose.yml  # see docker-compose.yml below
docker compose up -d

docker-compose.yml:

  services:
      node:
        image: node:16-alpine
        environment:
          - CHOKIDAR_USEPOLLING=true
          - FAST_REFRESH=true
        working_dir: /app
        ports:
          - '3000:3000'
        command: "yarn start"
        volumes:
          - './:/app'

open localhost:3000 in your browser. Hot reload should work out of the box.

Upvotes: 0

Eric
Eric

Reputation: 53

Not exactly a direct improvement of the author's code, but I was able to get a development environment working with very little code - and no direct dependency to node on my machine - like this:

docker-compose.yml

services:
  node:
    image: node:16
    user: "node"
    command: "npm start"
    working_dir: /app
    volumes:
      - ./:/app
    ports:
      - 3000:3000

This way, you avoid creating docker images from a Dockerfile.

Usage is generally like this:

  • install dependencies before running: docker compose run node npm install
  • run development environment: docker compose up
  • install new dependencies: docker compose run node npm install [package name]
  • clean up docker instances created with compose run: docker compose rm

Upvotes: 2

Xavier Lambros
Xavier Lambros

Reputation: 876

Running with CRA 4.0 and many dependencies

.dockerignore

.git
.gitignore
node_modules
build

Dockerfile.dev

FROM node:alpine

WORKDIR /app

COPY package.json /app

RUN yarn install

COPY . .

CMD ["yarn", "start"]

docker-compose.dev.yml

version: "3.8"
services:
  print:
    stdin_open: true
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ".:/app"
      - "/app/node_modules"

Dockerfile.prod

FROM node:alpine as build

WORKDIR /app

COPY package.json /app

RUN yarn install

COPY . /app

RUN yarn run build

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

docker-compose.prod.yml

version: "3.8"
services:
  print:
    stdin_open: true
    build:
      context: .
      dockerfile: Dockerfile.prod
    ports:
      - "80:80"

nginx.conf

server {  
  listen 80;
  server_name frontend;
  location / {
    root /usr/share/nginx/html;
    index index.html;
    try_files $uri /index.html;
  }
}

To run

docker-compose.exe -f .\docker-compose.yml up --build

or

docker-compose.exe -f .\docker-compose.dev.yml up --build

Upvotes: 1

Donny Verduijn
Donny Verduijn

Reputation: 454

While using docker in development with create-react-app, i discovered that it is possible to override the webpackDevServer configuration by adding CHOKIDAR_USEPOLLING=1to your .env file. This will make the file watching work again. It even refreshes the browser page on the host! The only thing that i discovered is that it doesn't open up a webpage automatically.

I can also advise to add tty: true to your service to have your original console output back into your terminal. To remove the container name prefixes in the logs, you can run something like this after running docker-compose up -d:

docker-compose logs -f --tail=100 client | cut -f2 -d \"|\""

Upvotes: 1

Ryabchenko Alexander
Ryabchenko Alexander

Reputation: 12450

here is good gide for this https://mherman.org/blog/dockerizing-a-react-app/

for development

# base image
FROM node:9.6.1

# set working directory
RUN mkdir /usr/src/app
WORKDIR /usr/src/app

# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install [email protected] -g --silent

# start app
CMD ["npm", "start"]

for production

# build environment
FROM node:9.6.1 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install [email protected] -g --silent
COPY . /usr/src/app
RUN npm run build

# production environment
FROM nginx:1.13.9-alpine
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Upvotes: 4

sh4
sh4

Reputation: 1265

I recently made a small project called hello-docker-react who just does what the op is looking for.

It's made with docker-compose, create-react-app, yarn, a node image, and a small entrypoint script.

Live reload work flawlessly and I haven't found any problems yet.

https://github.com/lopezator/hello-docker-react

Upvotes: 6

metakermit
metakermit

Reputation: 22341

Yeah, as aholbreich mentioned, I'd use npm install / npm start locally on my machine for development, just because it's so easy. It's probably possible with docker-compose, mounting volumes etc. too, but I think it could be a bit fiddly to set up.

For deployment you can then very easily use a Dockerfile. Here's an example Dockerfile I'm using:

FROM node:6.9

# Create app directory
RUN mkdir -p /src/app
WORKDIR /src/app

# to make npm test run only once non-interactively
ENV CI=true

# Install app dependencies
COPY package.json /src/app/
RUN npm install && \
    npm install -g pushstate-server

# Bundle app source
COPY . /src/app

# Build and optimize react app
RUN npm run build

EXPOSE 9000

# defined in package.json
CMD [ "npm", "run", "start:prod" ]

You need to add the start:prod option to your package.json:

"scripts": {
  "start": "react-scripts start",
  "start:prod": "pushstate-server build",
  "build": "react-scripts build",
  "test": "react-scripts test --env=jsdom",
  "eject": "react-scripts eject"
},

You can run the tests on your CI service with:

docker run <image> npm test

There's nothing stopping you from running this docker container locally as well to make sure things work as expected.

Upvotes: 10

Related Questions