Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dockerize client and server #45

Merged
merged 8 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

A basic web app client in the **/client** directory will show basic API usage and demonstration.

## Content

- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Available Scripts - server](#available-scripts---server)
- [Installation and Usage Using Docker](#installation-and-usage-using-docker)
- [Docker for Localhost Development](#docker-for-localhost-development)
- [Docker for Production Deployment](#docker-for-production-deployment)
- [References](#references)

## Requirements

1. Windows 10, MacOS, Linux
Expand Down Expand Up @@ -57,6 +68,7 @@ A basic web app client in the **/client** directory will show basic API usage an
- You can find this file in a Firebase project's
**Project Settings** -> **General** -> **Web apps** (Add an app if needed) -> **SDK setup and configuration**
3. Create a `/client/.env` file from the `/client/.env.example` file.
- The `firebase.config.js` settings must match with the `FIREBASE_SERVICE_ACC` environment variable provided on **server - step # 3.**
- Replace `REACT_APP_BASE_URL` with the domain on which the CRUD API is running (default value is `http://localhost:3001/api` on localhost. See the [server](#server) set-up instructions for more information).
4. Run the app in development mode.
`npm start`
Expand Down Expand Up @@ -85,7 +97,6 @@ A basic web app client in the **/client** directory will show basic API usage an
- Try signing in these users to the `/client` app.
- > **NOTE:** Comment out the `cors` options line `app.use(cors(corsOptions))` on **/server/src/index.js** when testing on Postman and other http clients other than the `/client` app.


## Available Scripts - server

The npm scripts listed below are available under the **/server** directory.
Expand Down Expand Up @@ -124,5 +135,52 @@ Copies the built `/client` website from `/client/build` to the server's root dir
```
- The built client app will be viewable on `http://localhost:3001` if the server is running.


## Installation and Usage Using Docker

We can use Docker to run dockerized **client** and **server** apps for local development. The following methods require Docker and Docker compose correctly installed and set up on your development machine.

### Docker for Localhost Development

1. Set-up the environment variables and firebase configuration file for the **/client** app.
- Create (your own) `firebase.config.js` file under `/client/utils/firebase/firebase.config.js` as advised on [**Installation - client # 2**](#client).
- Create the `.env` file under the **/client** directory as advised on [**Installation - client # 3**](#client).
2. Set-up the environment variables for the **/server** app.
- Create the `.env` file under the **/server** directory as advised on [**Installation - server # 3**](#server).
3. Build the client and server docker services for localhost development.
- `docker-compose -f docker-compose-dev.yml build`
- > **INFO:** Building the images for localhost development takes a while, around ~7min+.
4. Create and start the client and server containers.
`docker-compose -f docker-compose-dev.yml up`
5. Launch the dockerized (dev) client app on
`http://localhost:3000`
6. Launch the dockerized (dev) server app's API documentation on
`http://localhost:3001/docs`
7. Edit source the codes in `/client/src` or `/server/src` as needed. Verify that hot reload is working on both the client and server apps.
8. Stop and remove containers, networks, images and volumes:
`docker-compose -f docker-compose-dev.yml down`

### Docker for Production Deployment

The following docker-compose commands build small client and server images targeted for creating optimized dockerized apps running on production servers. Hot reload is not available when editing source codes from `/client/src` or `/server/src`.

1. Install and set up the required environment variables as with the required variables on **Docker for Localhost Development**.
2. Build the client and server docker services for production deployment.
- `docker-compose -f docker-compose-prod.yml build`
3. At this point, we can opt to push the docker images to a docker registry of your choice. (Requires sign-in to the selected docker registry).
- `docker-compose -f docker-compose-prod.yml push`
4. Create and start the client and server containers.
`docker-compose -f docker-compose-prod.yml up`
5. Launch the dockerized (prod) client app on
`http://localhost:3000`
6. Launch the dockerized (prod) server app's API documentation on
`http://localhost:3001/docs`
7. Stop and remove containers, networks, images and volumes:
`docker-compose -f docker-compose-prod.yml down`

## References

[[1]](https://docs.docker.com/compose/reference/) - docker compose commands

@ciatph
20220406
5 changes: 5 additions & 0 deletions client/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.git
.gitignore
node_modules
Dockerfile
.dockerignore
30 changes: 30 additions & 0 deletions client/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# BASE PROFILE
FROM node:14.19.3-alpine as base
RUN mkdir -p /opt/client
WORKDIR /opt/client
RUN adduser -S client
RUN chown -R client /opt/client
COPY package*.json ./

# BUILD TARGET
FROM base as build
RUN npm install && npm cache clean --force
COPY . ./
RUN npm run build
USER client

# DEVELOPMENT CLIENT PROFILE
FROM base as development
ENV NODE_ENV=development
RUN npm install && npm cache clean --force
COPY . ./
EXPOSE 3000
CMD ["npm", "start"]

# PRODUCTION CLIENT PROFILE
FROM nginx:1.22.0-alpine as production
COPY --from=build /opt/client/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]
19 changes: 19 additions & 0 deletions client/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
server {
listen 3000;
server_name localhost;

location /api {
proxy_pass http://server:3001;
}

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

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
30 changes: 30 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: "2.6.0"
services:
client-dev:
container_name: client-dev
image: ciatphdev/firebase-users-admin-client:dev
env_file:
- ./client/.env
build:
context: ./client
dockerfile: Dockerfile
target: development
volumes:
- ./client/public:/opt/client/public
- ./client/src:/opt/client/src
ports:
- "3000:3000"

server-dev:
container_name: server-dev
image: ciatphdev/firebase-users-admin-server:dev
env_file:
- ./server/.env
build:
context: ./server
dockerfile: Dockerfile
target: development
volumes:
- ./server/src:/opt/server/src
ports:
- "3001:3001"
25 changes: 25 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
version: "2.6.0"
services:
client-prod:
container_name: client-prod
image: ciatphdev/firebase-users-admin-client:latest
env_file:
- ./client/.env
build:
context: ./client
dockerfile: Dockerfile
target: production
ports:
- "3000:3000"

server-prod:
container_name: server-prod
image: ciatphdev/firebase-users-admin-server:latest
env_file:
- ./server/.env
build:
context: ./server
dockerfile: Dockerfile
target: production
ports:
- "3001:3001"
5 changes: 5 additions & 0 deletions server/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.git
.gitignore
node_modules
Dockerfile
.dockerignore
1 change: 0 additions & 1 deletion server/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
node_modules/
src/public/
.env
.env.dev
.env.prod
Expand Down
34 changes: 34 additions & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# BASE PROFILE
FROM node:14.19.3-alpine AS base
RUN mkdir -p /opt/server
WORKDIR /opt/server
RUN adduser -S server
RUN chown -R server /opt/server
COPY package*.json ./

# BUILD API DOCUMENTATION
FROM base as build
RUN npm install && npm cache clean --force
COPY . .
RUN npm run build

# PRODUCTION PROFILE TARGET
FROM base as production
ENV NODE_ENV production
RUN npm ci --only=production && npm cache clean --force
RUN npm install --save pm2
COPY . .
COPY --from=build /opt/server/public/docs ./public/docs
USER server
EXPOSE 3001
CMD ["npm", "run", "pm2"]

# DEVELOPMENT PROFILE TARGET
FROM base as development
ENV NODE_ENV development
RUN npm install && npm cache clean --force
COPY . .
COPY --from=build /opt/server/public/docs ./public/docs
USER server
EXPOSE 3001
CMD ["npm", "run", "dev"]
Loading