From b708b8e90ff05d73fc45040d938d241757f95f40 Mon Sep 17 00:00:00 2001 From: Chris Hartgerink Date: Fri, 22 Nov 2024 22:58:14 +0100 Subject: [PATCH] Add Docker --- .dockerignore | 18 +++++ .gitignore | 1 + Dockerfile | 154 ++++++++++++++++++++++++++++++++++++++++ api/package.json | 1 + docker-compose.dev.yml | 59 +++++++++++++++ docker-compose.prod.yml | 67 +++++++++++++++++ web/package.json | 1 + yarn.lock | 2 + 8 files changed, 303 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.dev.yml create mode 100644 docker-compose.prod.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f1d225c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +**/node_modules +**/dist +.redwood + +.env + +README.md +LICENSE + +.git +.gitignore + +.vscode +.editorconfig + +Dockerfile +docker-compose* +.dockerignore diff --git a/.gitignore b/.gitignore index 31d9637..0aa6507 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ api/src/lib/generateGraphiQLHeader.* !.yarn/releases !.yarn/sdks !.yarn/versions +mysql diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2749853 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,154 @@ +# base +# ---- +FROM node:20-bookworm-slim as base + +RUN corepack enable + +# We tried to make the Dockerfile as lean as possible. In some cases, that means we excluded a dependency your project needs. +# By far the most common is Python. If you're running into build errors because `python3` isn't available, +# add `python3 make gcc \` before the `openssl \` line below and in other stages as necessary: +RUN apt-get update && apt-get install -y \ + openssl \ + && rm -rf /var/lib/apt/lists/* + +USER node +WORKDIR /home/node/app + +COPY --chown=node:node .yarnrc.yml . +COPY --chown=node:node package.json . +COPY --chown=node:node api/package.json api/ +COPY --chown=node:node web/package.json web/ +COPY --chown=node:node yarn.lock . + +RUN mkdir -p /home/node/.yarn/berry/index +RUN mkdir -p /home/node/.cache + +RUN --mount=type=cache,target=/home/node/.yarn/berry/cache,uid=1000 \ + --mount=type=cache,target=/home/node/.cache,uid=1000 \ + CI=1 yarn install + +COPY --chown=node:node redwood.toml . +COPY --chown=node:node graphql.config.js . +COPY --chown=node:node .env.defaults .env.defaults + +# api build +# --------- +FROM base as api_build + +# If your api side build relies on build-time environment variables, +# specify them here as ARGs. (But don't put secrets in your Dockerfile!) +# +# ARG MY_BUILD_TIME_ENV_VAR + +COPY --chown=node:node api api +RUN yarn rw build api + +# web prerender build +# ------------------- +FROM api_build as web_build_with_prerender + +COPY --chown=node:node web web +RUN yarn rw build web + +# web build +# --------- +FROM base as web_build + +COPY --chown=node:node web web +RUN yarn rw build web --no-prerender + +# api serve +# --------- +FROM node:20-bookworm-slim as api_serve + +RUN corepack enable + +RUN apt-get update && apt-get install -y \ + openssl \ + && rm -rf /var/lib/apt/lists/* + +USER node +WORKDIR /home/node/app + +COPY --chown=node:node .yarnrc.yml . +COPY --chown=node:node package.json . +COPY --chown=node:node api/package.json api/ +COPY --chown=node:node yarn.lock . + +RUN mkdir -p /home/node/.yarn/berry/index +RUN mkdir -p /home/node/.cache + +RUN --mount=type=cache,target=/home/node/.yarn/berry/cache,uid=1000 \ + --mount=type=cache,target=/home/node/.cache,uid=1000 \ + CI=1 yarn workspaces focus api --production + +COPY --chown=node:node redwood.toml . +COPY --chown=node:node graphql.config.js . +COPY --chown=node:node .env.defaults .env.defaults + +COPY --chown=node:node --from=api_build /home/node/app/api/dist /home/node/app/api/dist +COPY --chown=node:node --from=api_build /home/node/app/api/db /home/node/app/api/db +COPY --chown=node:node --from=api_build /home/node/app/node_modules/.prisma /home/node/app/node_modules/.prisma + +ENV NODE_ENV=production + +# default api serve command +# --------- +# If you are using a custom server file, you must use the following +# command to launch your server instead of the default api-server below. +# This is important if you intend to configure GraphQL to use Realtime. +# +# CMD [ "./api/dist/server.js" ] +CMD [ "node_modules/.bin/rw-server", "api" ] + +# web serve +# --------- +FROM node:20-bookworm-slim as web_serve + +RUN corepack enable + +USER node +WORKDIR /home/node/app + +COPY --chown=node:node .yarnrc.yml . +COPY --chown=node:node package.json . +COPY --chown=node:node web/package.json web/ +COPY --chown=node:node yarn.lock . + +RUN mkdir -p /home/node/.yarn/berry/index +RUN mkdir -p /home/node/.cache + +RUN --mount=type=cache,target=/home/node/.yarn/berry/cache,uid=1000 \ + --mount=type=cache,target=/home/node/.cache,uid=1000 \ + CI=1 yarn workspaces focus web --production + +COPY --chown=node:node redwood.toml . +COPY --chown=node:node graphql.config.js . +COPY --chown=node:node .env.defaults .env.defaults + +COPY --chown=node:node --from=web_build /home/node/app/web/dist /home/node/app/web/dist + +ENV NODE_ENV=production \ + API_PROXY_TARGET=http://api:8911 + +# We use the shell form here for variable expansion. +CMD "node_modules/.bin/rw-web-server" "--api-proxy-target" "$API_PROXY_TARGET" + +# console +# ------- +FROM base as console + +# To add more packages: +# +# ``` +# USER root +# +# RUN apt-get update && apt-get install -y \ +# curl +# +# USER node +# ``` + +COPY --chown=node:node api api +COPY --chown=node:node web web +COPY --chown=node:node scripts scripts diff --git a/api/package.json b/api/package.json index 364bc10..2582fd5 100644 --- a/api/package.json +++ b/api/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@redwoodjs/api": "8.4.1", + "@redwoodjs/api-server": "8.4.1", "@redwoodjs/graphql-server": "8.4.1" } } diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..a33d6d1 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,59 @@ +services: + redwood: + build: + context: . + dockerfile: ./Dockerfile + target: base + command: yarn rw dev + volumes: + - .:/home/node/app + - node_modules:/home/node/app/node_modules + ports: + - '8910:8910' + depends_on: + - db + environment: + - DATABASE_URL=mysql://redwood:redwood@db:3306/redwood + - TEST_DATABASE_URL=mysql://redwood:redwood@db:3306/redwood_test + - SESSION_SECRET=super_secret_session_key_change_me_in_production_please + - CI= + - NODE_ENV=development + - REDWOOD_API_HOST=0.0.0.0 + + db: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: redwood + MYSQL_DATABASE: redwood + MYSQL_USER: redwood + MYSQL_PASSWORD: redwood + ports: + - '3306:3306' + volumes: + - mysql:/var/lib/mysql + + # After starting with `docker compose -f ./docker-compose.dev.yml up`, + # use the console to run commands in the container: + # + # ``` + # docker compose -f ./docker-compose.dev.yml run --rm -it console /bin/bash + # root@...:/home/node/app# yarn rw prisma migrate dev + # ``` + console: + user: root + build: + context: . + dockerfile: ./Dockerfile + target: console + tmpfs: + - /tmp + command: 'true' + environment: + - DATABASE_URL=mysql://redwood:redwood@db:3306/redwood + - TEST_DATABASE_URL=mysql://redwood:redwood@db:3306/redwood_test + depends_on: + - db + +volumes: + node_modules: + mysql: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..ad2927b --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,67 @@ +services: + api: + build: + context: . + dockerfile: ./Dockerfile + target: api_serve + # Without a command specified, the Dockerfile's api_serve CMD will be used. + # If you are using a custom server file, you should either use the following + # command to launch your server or update the Dockerfile to do so. + # This is important if you intend to configure GraphQL to use Realtime. + # command: "./api/dist/server.js" + ports: + - '8911:8911' + depends_on: + - db + environment: + - DATABASE_URL=mysql://redwood:redwood@db:3306/redwood + - TEST_DATABASE_URL=mysql://redwood:redwood@db:3306/redwood_test + - SESSION_SECRET=super_secret_session_key_change_me_in_production_please + + web: + build: + context: . + dockerfile: ./Dockerfile + target: web_serve + ports: + - '8910:8910' + depends_on: + - api + environment: + - API_PROXY_TARGET=http://api:8911 + + db: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: redwood + MYSQL_DATABASE: redwood + MYSQL_USER: redwood + MYSQL_PASSWORD: redwood + ports: + - '3306:3306' + volumes: + - mysql:/var/lib/mysql + + # After starting with `docker compose -f ./docker-compose.prod.yml up`, + # use the console to run commands in the container: + # + # ``` + # docker compose -f ./docker-compose.prod.yml run --rm -it console /bin/bash + # ``` + console: + user: root + build: + context: . + dockerfile: ./Dockerfile + target: console + tmpfs: + - /tmp + command: 'true' + environment: + - DATABASE_URL=mysql://redwood:redwood@db:3306/redwood + - TEST_DATABASE_URL=mysql://redwood:redwood@db:3306/redwood_test + depends_on: + - db + +volumes: + mysql: diff --git a/web/package.json b/web/package.json index 059b4f1..9e33e40 100644 --- a/web/package.json +++ b/web/package.json @@ -14,6 +14,7 @@ "@redwoodjs/forms": "8.4.1", "@redwoodjs/router": "8.4.1", "@redwoodjs/web": "8.4.1", + "@redwoodjs/web-server": "8.4.1", "react": "18.3.1", "react-dom": "18.3.1" }, diff --git a/yarn.lock b/yarn.lock index 91a798d..fe97f69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6403,6 +6403,7 @@ __metadata: resolution: "api@workspace:api" dependencies: "@redwoodjs/api": "npm:8.4.1" + "@redwoodjs/api-server": "npm:8.4.1" "@redwoodjs/graphql-server": "npm:8.4.1" languageName: unknown linkType: soft @@ -17123,6 +17124,7 @@ __metadata: "@redwoodjs/router": "npm:8.4.1" "@redwoodjs/vite": "npm:8.4.1" "@redwoodjs/web": "npm:8.4.1" + "@redwoodjs/web-server": "npm:8.4.1" "@types/react": "npm:^18.2.55" "@types/react-dom": "npm:^18.2.19" react: "npm:18.3.1"