Skip to content

Instantly share code, notes, and snippets.

@bhubr
Last active July 3, 2020 03:04
Show Gist options
  • Save bhubr/8d1acf9d213f20aaea4de3ed0cc15eda to your computer and use it in GitHub Desktop.
Save bhubr/8d1acf9d213f20aaea4de3ed0cc15eda to your computer and use it in GitHub Desktop.
CapRover full-stack deployment (Node.js/React)

Deploying Express+React+MySQL projects on CapRover

1. Create the app on the CapRover instance

First, head to https://your.caprover.instance.ext/ and fill in the password.

Then you have to replicate these steps for the Express and React apps:

  1. Under the "Apps" tab, fill in the input with your app's name and submit: your app should appear in the list.

  2. Click on your app in the list, under "HTTP Settings", click enable HTTPS

  3. Under the "Apps Config" tab, put your environment variables.

    • For example, in the example Express app linked below, I set up the CLIENT_APP_ORIGIN with the deployed React app's URL to authorize requests from that app.
    • In the React app, I set up the REACT_APP_API_BASE_URL with the deployed Express app's URL.

2. Install the CapRover CLI

npm install -g caprover

Then you can run (for example): caprover login (you'll be asked server URL and password).

2. Set up your Express app

Check out this minimal Express app's repo.

If you use Nodemon in development, make sure that you don't start Nodemon with npm start. So in your package.json, your scripts should look like:

  "scripts": {
      "start:dev": "nodemon src/server",
      "start": "node src/server",
      ...
  }

You need a captain-definition file at the root of your repo (you can specify Node version, as in this example, to whatever version you want):

{
  "schemaVersion": 2,
  "templateId": "node/12"
}

Here's a minimalist src/server.js file:

const express = require('express');
const cors = require('cors');
const app = express();

const corsOptions = {
  origin: process.env.CLIENT_APP_ORIGIN,
};
app.use(cors(corsOptions));

app.get('/', (req, res) => res.send('<h1>Hello World!</h1>'));

app.get('/api/meme', (req, res) => res.json({
  title: 'Node.js debugging meme',
  pictureUrl: 'https://miro.medium.com/max/1000/1*9bDq6pyYoXa39QxldAkf-g.jpeg'
}));

app.listen(process.env.PORT, (err) => {
  console.log('starting up server', err);
});

Deploy it by running caprover deploy (I haven't tried deploying with a git push).

3. Set up your React app

If you need in-depth instructions in CapRover's doc: https://caprover.com/docs/recipe-deploy-create-react-app.html

Basically there are two ways to set it up:

  • Let the target machine build the React app
  • Build the app locally, make a .tar archive out of it, and deploy this archived build

I went for the first option. The example repo is here: <>. I got almost everything from this official example: https://github.com/caprover/caprover/blob/master/captain-sample-apps/react-via-caprover.tar.

You need three files in your repo's root: captain-definition, default.conf and Dockerfile.

Here's my captain-definition file:

{
  "schemaVersion": 2,
  "dockerfilePath" :"./Dockerfile"
}

There's a default.conf file (Nginx config). Keep in mind that the React build consists only of static files, that's why we only need a static web server:

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;
  }
}

Last, there's Dockerfile. It's made of two parts, one for building the app, one for serving it. Note that this version slightly differs from the official example (I added ARG and ENV lines for in the build part, so that I could get the REACT_APP_API_BASE_URL environment variable set up in step 1):

# 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
ARG REACT_APP_API_BASE_URL=${REACT_APP_API_BASE_URL}
ENV REACT_APP_API_BASE_URL=${REACT_APP_API_BASE_URL}
COPY . /usr/src/app
RUN npm install
RUN npm run build

# production environment
FROM nginx:1.13.9-alpine
RUN rm -rf /etc/nginx/conf.d
RUN mkdir -p /etc/nginx/conf.d
COPY ./default.conf /etc/nginx/conf.d/
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Deploy it by running caprover deploy (I haven't tried deploying with a git push).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment