Skip to content
Open
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
23 changes: 23 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Frontend
NEXT_PUBLIC_STRAPI_BACKEND_SERVER="http://backend:1337"

# Backend
HOST=0.0.0.0
PORT=1337
APP_KEYS="jP8pb1lYsAhnmURarewxhA==,34xnLMYHY5jiU7ONTstTqQ=="
API_TOKEN_SALT="I0vcDalag4CrYczTEWBEDeM2yCJkza4tqtIl3/uhDn8="
ADMIN_JWT_SECRET="Sxtp8ZJi3lc0ZsAXZsP7phgUdajDFhOt8LzT+WXPCmXaMdRxXA35Cxud6G4eseoHEpq0UYzhCjzUvSuR4zzrg=="
TRANSFER_TOKEN_SALT="409wAPn4uEZOgPY3jLGrEb/QnQ+HlM7eRdJEmcGYcM8="
JWT_SECRET="ENOgRF5qx5vb8ynywbbGA1MJeQYWpzx1sZ7mSwNCI+dr3fqviCOZb1FaEc6zbAOPhvU6/DeAVRw+MY6MVPPbFw=="
NODE_ENV="production"

# Database
DATABASE_CLIENT=postgres
DATABASE_URL=postgres://strapi:strapi@database:5432/strapi
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=strapi
DATABASE_SSL=false

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/*.env
.env
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# Proposed Changes:

- Removed `appDir` at experimental feature in next.config.js
- Removed `@next/font` already built-in in Nextjs 14
- Added `Dockerfile` & `Dockerfile.prod` for easy CI/CD
- Added `compose.yml` for easy local development and testing with other `Docker` containers e.g `Postgres` database
- Added `.dockerignore` file
- Added `.justfile` for speeding command line productivity
- Added `.env` & `.env.example` files for both frotend and backend
9 changes: 9 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.tmp/
.cache/
.git/
.env
build/
node_modules/
# Ignoring folders that might be used in starter templates
data/
backup/
10 changes: 10 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ API_TOKEN_SALT=tobemodified
ADMIN_JWT_SECRET=tobemodified
TRANSFER_TOKEN_SALT=tobemodified
JWT_SECRET=tobemodified
NODE_ENV="development"

# Database
DATABASE_CLIENT=postgres
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=strapi
DATABASE_SSL=false
27 changes: 27 additions & 0 deletions backend/.justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# .justfile

# Default
default:
just --list

# Build Docker Image
# docker build \
# --build-arg NODE_ENV=production \
# # --build-arg STRAPI_URL=https://api.example.com \ # Uncomment to set the Strapi Server URL
# -t invoice-server:latest \ # Replace with your image name
# -f Dockerfile.prod .
build-image:
docker build --build-arg NODE_ENV=production -t invoice-server:latest -f Dockerfile.prod .

# Run Docker Container
run-container:
docker run -d -p 1337:1337 --network proxy-net --restart always --name invoice-backend invoice-server:latest

# Docker compose
run-compose:
docker compose up -d

# Docker compose down
run-compose-down:
docker compose down

19 changes: 19 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM node:18.18.2-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}

WORKDIR /opt/
COPY package.json yarn.lock ./
RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install
ENV PATH /opt/node_modules/.bin:$PATH

WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["yarn", "build"]
EXPOSE 1337
CMD ["yarn", "develop"]
28 changes: 28 additions & 0 deletions backend/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Creating multi-stage build for production
FROM node:18.18.2-alpine as build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ENV NODE_ENV=production

WORKDIR /opt/
COPY package.json yarn.lock ./
RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install --production
ENV PATH /opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN yarn build

# Creating final production image
FROM node:18.18.2-alpine
RUN apk add --no-cache vips-dev
ENV NODE_ENV=production
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
ENV PATH /opt/node_modules/.bin:$PATH

RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
CMD ["yarn", "start"]
7 changes: 4 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
},
"devDependencies": {},
"dependencies": {
"@strapi/strapi": "4.24.1",
"@strapi/plugin-users-permissions": "4.24.1",
"@strapi/plugin-i18n": "4.24.1",
"@strapi/plugin-cloud": "4.24.1",
"@strapi/plugin-i18n": "4.24.1",
"@strapi/plugin-users-permissions": "4.24.1",
"@strapi/strapi": "4.24.1",
"better-sqlite3": "8.6.0",
"pg": "^8.11.5",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "5.3.4",
Expand Down
85 changes: 84 additions & 1 deletion backend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7399,11 +7399,67 @@ pause@0.0.1:
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==

pg-cloudflare@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==

pg-connection-string@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.1.tgz#78c23c21a35dd116f48e12e23c0965e8d9e2cbfb"
integrity sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg==

pg-connection-string@^2.6.4:
version "2.6.4"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d"
integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==

pg-int8@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==

pg-pool@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2"
integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==

pg-protocol@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3"
integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==

pg-types@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
dependencies:
pg-int8 "1.0.1"
postgres-array "~2.0.0"
postgres-bytea "~1.0.0"
postgres-date "~1.0.4"
postgres-interval "^1.1.0"

pg@^8.11.5:
version "8.11.5"
resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.5.tgz#e722b0a5f1ed92931c31758ebec3ddf878dd4128"
integrity sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==
dependencies:
pg-connection-string "^2.6.4"
pg-pool "^3.6.2"
pg-protocol "^1.6.1"
pg-types "^2.1.0"
pgpass "1.x"
optionalDependencies:
pg-cloudflare "^1.1.1"

pgpass@1.x:
version "1.0.5"
resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"
integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==
dependencies:
split2 "^4.1.0"

picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
Expand Down Expand Up @@ -7500,6 +7556,28 @@ postcss@^8.3.11, postcss@^8.4.32, postcss@^8.4.33:
picocolors "^1.0.0"
source-map-js "^1.2.0"

postgres-array@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==

postgres-bytea@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==

postgres-date@~1.0.4:
version "1.0.7"
resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8"
integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==

postgres-interval@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
dependencies:
xtend "^4.0.0"

prebuild-install@^7.1.1:
version "7.1.2"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.2.tgz#a5fd9986f5a6251fbc47e1e5c65de71e68c0a056"
Expand Down Expand Up @@ -8694,6 +8772,11 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"

split2@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==

sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
Expand Down Expand Up @@ -9631,7 +9714,7 @@ xdg-basedir@^4.0.0:
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==

xtend@~4.0.1:
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
Expand Down
75 changes: 75 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
services:
frontend:
container_name: invoice-client
build: ./frontend
image: invoice-client:latest
restart: unless-stopped
environment:
- NEXT_PUBLIC_STRAPI_BACKEND_SERVER=${NEXT_PUBLIC_STRAPI_BACKEND_SERVER}
ports:
- "3333:3000"
networks:
- proxy-net
depends_on:
- backend

backend:
container_name: invoice-server
build:
context: ./backend
dockerfile: Dockerfile.prod
image: invoice-server:latest
restart: unless-stopped
env_file: ./backend/.env
environment:
DATABASE_CLIENT: ${DATABASE_CLIENT}
DATABASE_HOST: ${DATABASE_HOST}
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
APP_KEYS: ${APP_KEYS}
NODE_ENV: ${NODE_ENV}
volumes:
- ./backend/config:/opt/app/config
- ./backend/src:/opt/app/src
- ./backend/package.json:/opt/package.json
- ./backend/yarn.lock:/opt/yarn.lock
- ./backend/.env:/opt/app/.env
- ./backend/public/uploads:/opt/app/public/uploads
ports:
- "1337:1337"
networks:
- proxy-net
depends_on:
- database

database:
container_name: invoice-database
platform: linux/amd64 #for platform error on Apple M1 chips
restart: unless-stopped
env_file: ./backend/.env
image: postgres:15.5-alpine
environment:
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
volumes:
- strapi-data:/var/lib/postgresql/data/ #using a volume
#- ./data:/var/lib/postgresql/data/ # if you want to use a bind folder

ports:
- "5432:5432"
networks:
- proxy-net

volumes:
strapi-data:

networks:
proxy-net:
name: proxy-net
driver: bridge
external: true
6 changes: 6 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.tmp/
.cache/
.git/
build/
node_modules/

1 change: 1 addition & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_STRAPI_BACKEND_SERVER="http://localhost:1337"
22 changes: 22 additions & 0 deletions frontend/.justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# .justfile

# Default
default:
just --list

# Build Docker Image
build-image:
docker build -t invoice-client:latest .

# Run Docker Container
run-container:
docker run -d -p 3333:3000 --network proxy-net --restart always --name invoice-client invoice-client:latest

# Docker compose
run-compose:
docker compose up -d

# Docker compose down
run-compose-down:
docker compose down

8 changes: 8 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM node:18.18.2-alpine as build
WORKDIR /app
COPY . .
RUN npm ci --silent
RUN npm run build

FROM lipanski/docker-static-website:2.3.0 as release
COPY --from=build /app/dist .
Loading