Skip to content
Akram El Assas edited this page May 12, 2024 · 76 revisions

BookCars can run in a Docker container on Linux and Docker Desktop for Windows or Mac.

Docker Image

This section describes how to build BookCars Docker image and run it in a Docker container.

  1. Clone BookCars repo:
git clone https://github.com/aelassas/bookcars.git
  1. Create ./api/.env.docker file with the following content:
NODE_ENV=production
BC_PORT=4002
BC_HTTPS=false
BC_PRIVATE_KEY=/etc/ssl/bookcars.key
BC_CERTIFICATE=/etc/ssl/bookcars.crt
BC_DB_URI=mongodb://admin:PASSWORD@mongo:27017/bookcars?authSource=admin&appName=bookcars
BC_DB_SSL=false
BC_DB_SSL_CERT=/etc/ssl/bookcars.crt
BC_DB_SSL_CA=/etc/ssl/bookcars.ca.pem
BC_DB_DEBUG=false
BC_COOKIE_SECRET=COOKIE_SECRET
BC_AUTH_COOKIE_DOMAIN=localhost
BC_JWT_SECRET=JWT_SECRET
BC_JWT_EXPIRE_AT=86400
BC_TOKEN_EXPIRE_AT=86400
BC_SMTP_HOST=smtp.sendgrid.net
BC_SMTP_PORT=587
BC_SMTP_USER=apikey
BC_SMTP_PASS=PASSWORD
BC_SMTP_FROM=admin@bookcars.ma
BC_CDN_USERS=/var/www/cdn/bookcars/users
BC_CDN_TEMP_USERS=/var/www/cdn/bookcars/temp/users
BC_CDN_CARS=/var/www/cdn/bookcars/cars
BC_CDN_TEMP_CARS=/var/www/cdn/bookcars/temp/cars
BC_DEFAULT_LANGUAGE=en
BC_BACKEND_HOST=http://localhost:3001/
BC_FRONTEND_HOST=http://localhost/
BC_MINIMUM_AGE=21
BC_EXPO_ACCESS_TOKEN=EXPO_ACCESS_TOKEN
BC_STRIPE_SECRET_KEY=STRIPE_SECRET_KEY
BC_ADMIN_EMAIL=admin@bookcars.ma

Set the following options:

BC_DB_URI=mongodb://admin:PASSWORD@mongo:27017/bookcars?authSource=admin&appName=bookcars
BC_COOKIE_SECRET=COOKIE_SECRET
BC_AUTH_COOKIE_DOMAIN=localhost
BC_JWT_SECRET=JWT_SECRET
BC_SMTP_HOST=smtp.sendgrid.net
BC_SMTP_PORT=587
BC_SMTP_USER=apikey
BC_SMTP_PASS=PASSWORD
BC_SMTP_FROM=admin@bookcars.com
BC_BACKEND_HOST=http://localhost:3001/
BC_FRONTEND_HOST=http://localhost/

If you want to use MongoDB Atlas, put you MongoDB Atlas URI in BC_DB_URI otherwise replace PASSWORD in BC_DB_URI with your MongoDB password. Replace JWT_SECRET with a secret token. Finally, set the SMTP options. SMTP options are necessary for sign up. You can use sendgrid or any other transactional email provider.

If you choose sendgrid, create an account on sendgrid.com, login and go to the dashboard. On the left panel, click on Email API, then on Integration Guide. Then, choose SMTP Relay and follow the steps. You will be prompted to create an API Key. Once you create the API Key and verify the smtp relay, copy the API key in BC_SMTP_PASS in ./api/.env. Sendgrid's free plan allows to send up to 100 emails/day. If you need to send more than 100 emails/day, switch to a paid plan or choose another transactional email provider.

COOKIE_SECRET and JWT_SECRET should at least be 32 characters long, but the longer the better. You can use an online password generator and set the password length to 32 or longer.

The following settings are very important and if they are not set properly, authentication won't work:

BC_AUTH_COOKIE_DOMAIN=localhost
BC_BACKEND_HOST=http://localhost:3001/
BC_FRONTEND_HOST=http://localhost/

Replace localhost with an IP or FQDN. That is if you access the backend from http://<FQDN>:3001/. BC_BACKEND_HOST should be http://<FQDN>:3001/. The same goes for BC_FRONTEND_HOST. And BC_AUTH_COOKIE_DOMAIN should be FQDN.

Leave localhost if you want to test locally.

If you want to enable push notifications in the mobile app, follow these instructions and set the following option:

BC_EXPO_ACCESS_TOKEN=EXPO_ACCESS_TOKEN

If you want to enable stripe payment gateway, sign up for a stripe account, fill the forms and save the publishable key and the secret key from stripe dashboard. Then, set the secret key in the following option in api/.env:

BC_STRIPE_SECRET_KEY=STRIPE_SECRET_KEY

Don't expose stripe secret key on a website or embed it in a mobile application. It must be secret and stored securely in the server-side.

In stripe, all accounts have a total of four API keys by default-two for test mode and two for live mode:

  • Test mode secret key: Use this key to authenticate requests on your server when in test mode. By default, you can use this key to perform any API request without restriction.
  • Test mode publishable key: Use this key for testing purposes in your web or mobile app’s client-side code.
  • Live mode secret key: Use this key to authenticate requests on your server when in live mode. By default, you can use this key to perform any API request without restriction.
  • Live mode publishable key: Use this key, when you’re ready to launch your app, in your web or mobile app’s client-side code.

Use only your test API keys for testing. This ensures that you don't accidentally modify your live customers or charges.

  1. Create ./backend/.env.docker file with the following content:
REACT_APP_NODE_ENV=production
REACT_APP_BC_API_HOST=http://localhost:4002
REACT_APP_BC_DEFAULT_LANGUAGE=en
REACT_APP_BC_PAGE_SIZE=30
REACT_APP_BC_CARS_PAGE_SIZE=15
REACT_APP_BC_BOOKINGS_PAGE_SIZE=20
REACT_APP_BC_BOOKINGS_MOBILE_PAGE_SIZE=10
REACT_APP_BC_CDN_USERS=http://localhost/cdn/bookcars/users
REACT_APP_BC_CDN_TEMP_USERS=http://localhost/cdn/bookcars/temp/users
REACT_APP_BC_CDN_CARS=http://localhost/cdn/bookcars/cars
REACT_APP_BC_CDN_TEMP_CARS=http://localhost/cdn/bookcars/temp/cars
REACT_APP_BC_SUPPLIER_IMAGE_WIDTH=60
REACT_APP_BC_SUPPLIER_IMAGE_HEIGHT=30
REACT_APP_BC_CAR_IMAGE_WIDTH=300
REACT_APP_BC_CAR_IMAGE_HEIGHT=200
REACT_APP_BC_MINIMUM_AGE=21
REACT_APP_BC_PAGINATION_MODE=classic

Set the following options:

REACT_APP_BC_API_HOST=http://localhost:4002
REACT_APP_BC_CDN_USERS=http://localhost/cdn/bookcars/users
REACT_APP_BC_CDN_TEMP_USERS=http://localhost/cdn/bookcars/temp/users
REACT_APP_BC_CDN_CARS=http://localhost/cdn/bookcars/cars
REACT_APP_BC_CDN_TEMP_CARS=http://localhost/cdn/bookcars/temp/cars

The following settings are very important and if they are not set properly, authentication won't work:

BC_AUTH_COOKIE_DOMAIN=localhost
BC_BACKEND_HOST=http://localhost:3001/
BC_FRONTEND_HOST=http://localhost/

Replace localhost with an IP or FQDN. That is if you access the backend from http://:3001/. BC_BACKEND_HOST should be http://:3001/. The same goes for BC_FRONTEND_HOST. And BC_AUTH_COOKIE_DOMAIN should be FQDN.

Leave localhost if you want to test locally.

If you want to change pagination mode, change REACT_APP_BC_PAGINATION_MODE option. You can choose between classic or infinite_scroll. This option defaults to classic. If you choose classic, you will get a classic pagination with next and previous buttons on desktop and infinite scroll on mobile. If you choose infinite_scroll, you will get infinite scroll on desktop and mobile.

  1. Create ./frontend/.env.docker file with the following content:
REACT_APP_NODE_ENV=production
REACT_APP_BC_API_HOST=http://localhost:4002
REACT_APP_BC_RECAPTCHA_ENABLED=false
REACT_APP_BC_DEFAULT_LANGUAGE=en
REACT_APP_BC_PAGE_SIZE=30
REACT_APP_BC_CARS_PAGE_SIZE=15
REACT_APP_BC_BOOKINGS_PAGE_SIZE=20
REACT_APP_BC_BOOKINGS_MOBILE_PAGE_SIZE=10
REACT_APP_BC_CDN_USERS=http://localhost/cdn/bookcars/users
REACT_APP_BC_CDN_CARS=http://localhost/cdn/bookcars/cars
REACT_APP_BC_SUPPLIER_IMAGE_WIDTH=60
REACT_APP_BC_SUPPLIER_IMAGE_HEIGHT=30
REACT_APP_BC_CAR_IMAGE_WIDTH=300
REACT_APP_BC_CAR_IMAGE_HEIGHT=200
REACT_APP_BC_MINIMUM_AGE=21
REACT_APP_BC_PAGINATION_MODE=classic
REACT_APP_BC_STRIPE_PUBLISHABLE_KEY=STRIPE_PUBLISHABLE_KEY
REACT_APP_BC_STRIPE_CURRENCY_CODE=USD

Set the following options:

REACT_APP_BC_API_HOST=http://localhost:4002
REACT_APP_BC_CDN_USERS=http://localhost/cdn/bookcars/users
REACT_APP_BC_CDN_CARS=http://localhost/cdn/bookcars/cars
REACT_APP_BC_STRIPE_PUBLISHABLE_KEY=STRIPE_PUBLISHABLE_KEY
REACT_APP_BC_STRIPE_CURRENCY_CODE=USD

Leave localhost if you want to test locally or Replace it with an IP, hostname or FQDN.

If you want to enable stripe payment gateway, set stripe publishable key in REACT_APP_BC_STRIPE_PUBLISHABLE_KEY. You can retrieve it from stripe dashboard.

REACT_APP_BC_STRIPE_CURRENCY_CODE is the three-letter ISO 4217 alphabetic currency code, e.g. "USD" or "EUR". Required for Stripe payments. Must be a supported currency: https://docs.stripe.com/currencies

If you want to change pagination mode, change REACT_APP_BC_PAGINATION_MODE option.

reCAPTCHA is by default disabled on the frontend. If you want to enable it, you have to set REACT_APP_BC_RECAPTCHA_ENABLED to true and REACT_APP_BC_RECAPTCHA_SITE_KEY to Google reCAPTCHA site key.

  1. Open ./docker-compose.yml and set MongoDB password:
version: "3.8"
services:
  api:
    build: 
      context: .
      dockerfile: ./api/Dockerfile
    env_file: ./api/.env.docker
    restart: always
    ports:
      - 4002:4002
    depends_on:
      - mongo
    volumes:
      - cdn:/var/www/cdn/bookcars

  mongo:
    image: mongo:latest
    command: mongod --quiet --logpath /dev/null
    restart: always
    environment:
      # Provide your credentials here
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: PASSWORD
    ports:
      - 27017:27017

  backend:
    build: 
      context: .
      dockerfile: ./backend/Dockerfile
    depends_on:
      - api
    ports:
      - 3001:3001

  frontend:
    build: 
      context: .
      dockerfile: ./frontend/Dockerfile
    depends_on:
      - api
    ports:
      - 80:80
    volumes:
      - cdn:/var/www/cdn/bookcars

volumes:
  cdn:

If you want to use MongoDB Atlas, remove mongo container. Otherwise, replace PASSWORD with the password that you have set in BC_DB_URI in ./api/.env.docker.

  1. Build and run docker image:
docker compose up

To run the compose in background, add the -d option with the command:

docker compose up -d

If you want to rebuild, use the following commands:

docker compose build --no-cache
docker compose up

If you want to check the logs of the containers for troubleshooting, use the following command:

docker compose logs

If you want to stop and remove containers, volumes, networks, and images created by docker-compose up, and start from a clean image, use the following commands:

docker compose down --volumes
docker compose build --no-cache
docker compose up

Be careful when using the commands above. MongoDB database and cdn content will be deleted. So make sure you backup the database and cdn content before to run these commands.

That's it! BookCars backend is accessible from http://<hostname>:3001 and BookCars frontend is accessible from http://<hostname>.

If you run BookCars for the first time, you'll start from an empty database. So you have to create an admin user from the backend by filling the from http://<hostname>:3001/sign-up. SMTP settings must configured to process sign up. Then, secure the backend by opening backend/src/App.tsx and commenting the following lines:

const SignUp = lazy(() => import('./pages/SignUp'))
<Route exact path='/sign-up' element={<Signup />} />

You'll need to rebuild and run Docker image:

docker compose build --no-cache
docker compose up

Once you create the admin user, do the following:

  • Go to the suppliers page and create one or multiple suppliers
  • Go to the locations page and create one or multiple locations
  • Go to the cars page and create one or multiple cars
  • Go to the frontend, sign up, choose a car and checkout.

Finally, you will see bookings listed in the backend dashboard.

You can use the demo database if you want to.

Below are Docker configuration files:

That's it. You can explore the other pages in the backend and the frontend.

SSL

This section will walk you through how to enable SSL in the API, the backend and the frontend in a docker container.

Copy your private key bookcars.key and your certificate bookcars.crt in ./.

bookcars.key will be loaded as /etc/ssl/bookcars.key and bookcars.crt will be loaded as /etc/ssl/bookcars.crt in ./docker-compose.yml.

API

For the API, update ./api/.env.docker as follows to enable SSL:

BC_HTTPS=true
BC_PRIVATE_KEY=/etc/ssl/bookcars.key
BC_CERTIFICATE=/etc/ssl/bookcars.crt
BC_BACKEND_HOST=http://localhost:3001/
BC_FRONTEND_HOST=http://localhost/

Replace http://localhost with https://<fqdn>.

Backend

For the backend, update the following options in ./backend/.env.docker:

REACT_APP_BC_API_HOST=http://localhost:4002
REACT_APP_BC_CDN_USERS=http://localhost/cdn/bookcars/users
REACT_APP_BC_CDN_TEMP_USERS=http://localhost/cdn/bookcars/temp/users
REACT_APP_BC_CDN_CARS=http://localhost/cdn/bookcars/cars
REACT_APP_BC_CDN_TEMP_CARS=http://localhost/cdn/bookcars/temp/cars

Replace http://localhost with https://<fqdn>.

Then, update ./backend/nginx.conf as follows to enable SSL:

server {
    listen 3001 ssl;
    root /usr/share/nginx/html;
    index index.html;

    ssl_certificate_key /etc/ssl/bookcars.key;
    ssl_certificate /etc/ssl/bookcars.crt;

    error_page 497 301 =307 https://$host:$server_port$request_uri;

    access_log /var/log/nginx/backend.access.log;
    error_log /var/log/nginx/backend.error.log;

    location / {
        # First attempt to serve request as file, then as directory,
        # then as index.html, then fall back to displaying a 404.
        try_files $uri $uri/ /index.html =404;
    }
}

Frontend

For the frontend, update the following options in ./frontend/.env.docker:

REACT_APP_BC_API_HOST=http://localhost:4002
REACT_APP_BC_CDN_USERS=http://localhost/cdn/bookcars/users
REACT_APP_BC_CDN_CARS=http://localhost/cdn/bookcars/cars

Replace http://localhost with https://<fqdn>.

Add the port 443 to ./frontend/Dokerfile as follows:

# syntax=docker/dockerfile:1

FROM node:lts-alpine as build
WORKDIR /bookcars/frontend
COPY ./frontend ./
COPY ./frontend/.env.docker .env
COPY ./packages /bookcars/packages
RUN npm install
RUN npm run build

FROM nginx:stable-alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf *
COPY --from=build /bookcars/frontend/build .
COPY ./frontend/nginx.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80
EXPOSE 443

Then, update ./frontend/nginx.conf as follows to enable SSL:

server {
    listen 80;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    root /usr/share/nginx/html;
    index index.html;

    ssl_certificate_key /etc/ssl/bookcars.key;
    ssl_certificate /etc/ssl/bookcars.crt;

    access_log /var/log/nginx/frontend.access.log;
    error_log /var/log/nginx/frontend.error.log;

    location / {
      # First attempt to serve request as file, then as directory,
      # then as index.html, then fall back to displaying a 404.
      try_files $uri $uri/ /index.html =404;
    }

    location /cdn {
      alias /var/www/cdn;
    }
}

docker-compose.yml

Update ./docker-compose.yml to load your private key bookcars.key and your certificate bookcars.crt, and add the port 443 to the frontend as follows:

version: "3.8"
services:
  api:
    build: 
      context: .
      dockerfile: ./api/Dockerfile
    env_file: ./api/.env.docker
    restart: always
    ports:
      - 4002:4002
    depends_on:
      - mongo
    volumes:
      - cdn:/var/www/cdn/bookcars
      - ./bookcars.key:/etc/ssl/bookcars.key
      - ./bookcars.crt:/etc/ssl/bookcars.crt

  mongo:
    image: mongo:latest
    restart: always
    environment:
      # Provide your credentials here
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: PASSWORD
    ports:
      - 27017:27017

  backend:
    build: 
      context: .
      dockerfile: ./backend/Dockerfile
    depends_on:
      - api
    ports:
      - 3001:3001
    volumes:
      - ./bookcars.key:/etc/ssl/bookcars.key
      - ./bookcars.crt:/etc/ssl/bookcars.crt

  frontend:
    build: 
      context: .
      dockerfile: ./frontend/Dockerfile
    depends_on:
      - api
    ports:
      - 80:80
      - 443:443
    volumes:
      - cdn:/var/www/cdn/bookcars
      - ./bookcars.key:/etc/ssl/bookcars.key
      - ./bookcars.crt:/etc/ssl/bookcars.crt

volumes:
  cdn:

Rebuild and run Docker image:

docker compose build --no-cache
docker compose up