Skip to content

Commit f50f9d2

Browse files
authored
Merge pull request #50 from scio-labs/feat/29-dockerfile-for-development-and-optional-deployment
feat: Setup Dockerfile for frontend app build
2 parents 4c1f1c5 + df36d02 commit f50f9d2

7 files changed

+167
-22
lines changed

.changeset/early-pens-itch.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@inkathon/frontend": minor
3+
"@inkathon/contracts": minor
4+
---
5+
6+
- Setup Docker workflow for local development of frontend (Next.js Startup & Watching) and production build (non-Vercel deployments)
7+
- Setup Docker workflow for local development of contracts (Rust & Substrate Contracts Node Setup, Contract Deployment)

Dockerfile.contracts

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
FROM paritytech/ci-linux:production as builder
2+
3+
WORKDIR /app
4+
COPY . .
5+
6+
# Switch from sh to bash
7+
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
8+
9+
RUN apt update
10+
11+
RUN echo "**Getting Ubuntu and Rust dependencies**"
12+
RUN apt install -y build-essential pkg-config git clang curl libssl-dev llvm libudev-dev
13+
14+
RUN echo "**Installing node.js, pnpm, and package dependencies**"
15+
# Install nvm and node
16+
RUN mkdir -p /usr/local/nvm
17+
ENV NVM_DIR /usr/local/nvm
18+
ENV NODE_VERSION v20.9.0
19+
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
20+
RUN /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION && nvm use --delete-prefix $NODE_VERSION"
21+
ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/bin
22+
ENV PATH $NODE_PATH:$PATH
23+
# Install pnpm
24+
RUN npm i --global --no-update-notifier --no-fund pnpm@8
25+
RUN yes Y | pnpm install
26+
27+
RUN echo "*** Instaling Rust environment for contracts node***"
28+
RUN rm -rf /usr/local/rustup /usr/local/cargo
29+
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
30+
ENV PATH="/root/.cargo/bin:${PATH}"
31+
RUN rustup default stable
32+
RUN rustup update
33+
RUN rustup target add wasm32-unknown-unknown
34+
RUN rustup update nightly
35+
RUN rustup target add wasm32-unknown-unknown --toolchain nightly
36+
RUN rustup show
37+
RUN rustup +nightly show
38+
RUN cargo install contracts-node
39+
40+
RUN echo "*** Installing cargo-contract ***"
41+
RUN rustup component add rust-src
42+
RUN cargo install --force --locked cargo-contract
43+
44+
# Set and expose the port that the app will run on
45+
EXPOSE 9944
46+
47+
# RUN echo "*** Start Substrate node template ***"
48+
CMD [ "/usr/local/cargo/bin/substrate-contracts-node", "--dev", "--rpc-cors=all"]

Dockerfile.frontend

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Inspired by https://www.darraghoriordan.com/2023/04/13/running-next-js-docker-container
2+
# STAGE 1: A container with pnpm and python3 is required
3+
FROM node:18-alpine as pnpm_base
4+
5+
WORKDIR /app
6+
# install pnpm
7+
RUN npm i --global --no-update-notifier --no-fund pnpm@8 \
8+
# install python3 and other deps
9+
&& apk add --no-cache g++=~13.2.1_git20231014-r0 make=~4.4.1-r2 py3-pip libc6-compat bash=~5.2.21-r0
10+
11+
12+
# STAGE 2: fetch deps into the pnpm store
13+
# We run pnpm fetch in a separate step to avoid re-fetching deps on every code change
14+
FROM pnpm_base as fetched_deps
15+
WORKDIR /app
16+
# setting env to production usually speeds up installations
17+
ENV NODE_ENV=production
18+
COPY pnpm-lock.yaml ./
19+
# set the store dir to a folder that is not in the project
20+
RUN pnpm config set store-dir /workdir/.pnpm-store \
21+
&& pnpm fetch
22+
23+
# STAGE 3: Copy the application code and install all deps from cache into the application
24+
FROM fetched_deps as with_all_deps
25+
# Copy whole project since it's using monorepo
26+
COPY . ./
27+
# Install all the deps
28+
RUN pnpm install --offline
29+
30+
# STAGE 4: Build the NextJS app
31+
# Use pnpm filter to only build the frontend app
32+
# Then use pnpm deploy command to prune the dependencies
33+
FROM with_all_deps as builder
34+
RUN pnpm --filter='*frontend' build \
35+
&& pnpm --filter='*frontend' deploy pruned --prod
36+
37+
# STAGE 5: Create a clean production image - only take pruned assets
38+
FROM node:18-alpine AS runner
39+
WORKDIR /app
40+
# We set the NODE_ENV to production to make sure that the app runs in production mode
41+
ENV NODE_ENV=production
42+
# We add a non-root user to run the app for security reasons
43+
RUN addgroup --system --gid 1001 app \
44+
&& adduser --system --uid 1001 app
45+
USER app
46+
47+
# Copy the built app assets from the builder stage
48+
# NextJS produces a backend server and a frontend app
49+
COPY --chown=app:app --from=builder /app/frontend/.next/standalone src/
50+
COPY --chown=app:app --from=builder /app/frontend/public src/frontend/public
51+
COPY --chown=app:app --from=builder /app/frontend/.next/static src/frontend/.next/static
52+
53+
# Set and expose the port that the app will run on
54+
ENV PORT 3000
55+
EXPOSE 3000
56+
57+
# Run the app
58+
CMD ["node", "src/frontend/server.js"]

README.md

+11-22
Original file line numberDiff line numberDiff line change
@@ -187,29 +187,9 @@ Spinning up a deployment via Vercel is pretty straightforward as the necessary s
187187

188188
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fhello-world&env=NEXT_PUBLIC_DEFAULT_CHAIN&envDescription=Insert%20%60alephzero-testnet%60%20or%20%60shibuya%60&envLink=https%3A%2F%2Fgithub.com%2Fscio-labs%2Finkathon%23environment-variables&project-name=inkathon&repository-name=inkathon&redirect-url=https%3A%2F%2Fgithub.com%2Fscio-labs%2Finkathon&demo-url=https%3A%2F%2Finkathon.xyz)
189189

190-
### Environment Variables
191-
192-
One key element making this boilerplate so flexible is the usage of environment variables to configure the active network in the frontend. This is done by setting the `NEXT_PUBLIC_DEFAULT_CHAIN` variable in the `frontend/.env.local` file, or in the Vercel deployment settings respectively.
193-
194-
<details>
195-
<summary><strong>All Supported Chain Constants</strong></summary>
196-
197-
| Network Identifier | Name | Type |
198-
| ------------------- | ----------------------- | ------- |
199-
| `development` | ️Local Development Node | Testnet |
200-
| `alephzero-testnet` | Aleph Zero Testnet | Testnet |
201-
| `rococo` | Rococo | Testnet |
202-
| `shibuya` | Shibuya Testnet | Testnet |
203-
| `shiden` | Shiden | Mainnet |
204-
| `alephzero` | Aleph Zero | Mainnet |
205-
| `astar` | Astar | Mainnet |
206-
207-
<small>Source: https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts</small>
208-
209-
> [!NOTE]
210-
> Chains can also be supplied manually by creating a [`SubstrateChain`](https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts#L4) object. If you think a chain is missing, please open an issue or PR.
190+
Alternatively, you can also use the provided Dockerfiles to deploy to any hosting provider of your choice. Read more [here](https://github.com/scio-labs/inkathon/pull/50#issue-2041934251).
211191

212-
</details>
192+
### Environment Variables
213193

214194
All environment variables are imported from `process.env` in [`frontend/src/config/environment.ts`](https://github.com/scio-labs/inkathon/blob/main/frontend/src/config/environment.ts) and re-exported from there. For improved type safety, Always only import environment variables from `@/config/environment` and never directly from `process.env`.
215195

@@ -222,6 +202,15 @@ All environment variables are imported from `process.env` in [`frontend/src/conf
222202

223203
<small>\*️⃣ Required </small>
224204

205+
#### Supported Chains
206+
207+
One key element making this boilerplate so flexible is the usage of environment variables to configure the active network in the frontend. This is done by setting the `NEXT_PUBLIC_DEFAULT_CHAIN` variable in the `frontend/.env.local` file, or in the deployment settings respectively.
208+
209+
If your network is not provided by the `use-inkathon` library, you can add it manually by creating a new [`SubstrateChain`](https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts#L4) object. If you think a chain is missing, please open an issue or PR.
210+
211+
> [!IMPORTANT]
212+
> All supported chain constants [can be found here](https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts) in the `scio-labs/use-inkathon` repository.
213+
225214
### Contract Deployment
226215

227216
In the [Getting Started](#getting-started) section above, we've already deployed the sample `Greeter` contract on a local node. To target a live network, we can use the `CHAIN` environment variable when running the `deploy` script.

docker-compose.contracts.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: '1.0'
2+
3+
services:
4+
substrate-contracts-node:
5+
build:
6+
context: .
7+
dockerfile: Dockerfile.contracts
8+
image: contracts-node:latest
9+
container_name: substrate-contracts-node
10+
ports:
11+
- "9944:9944"

docker-compose.frontend.yaml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
version: '1.0'
2+
services:
3+
frontend-dev:
4+
container_name: inkathon-frontend-dev
5+
build:
6+
context: .
7+
dockerfile: Dockerfile.frontend
8+
target: with_all_deps
9+
restart: always
10+
command: pnpm run dev
11+
environment:
12+
- NODE_ENV=development
13+
- CHOKIDAR_USEPOLLING=true
14+
- WATCHPACK_POLLING=true
15+
volumes:
16+
- .:/app
17+
- /app/node_modules
18+
- /app/.next
19+
ports:
20+
- 3000:3000
21+
frontend-prod:
22+
container_name: inkathon-frontend-prod
23+
build:
24+
context: .
25+
dockerfile: Dockerfile.frontend
26+
args:
27+
- NODE_ENV=production
28+
ports:
29+
- 3001:3000

frontend/next.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/* eslint-env node */
33
// @ts-check
44

5+
const path = require('path')
6+
57
/**
68
* @type {import('next').NextConfig}
79
**/
@@ -10,6 +12,7 @@ const nextConfig = {
1012
// Fix for warnings about cjs/esm package duplication
1113
// See: https://github.com/polkadot-js/api/issues/5636
1214
transpilePackages: ['@polkadot/.*'],
15+
output: 'standalone',
1316
}
1417

1518
module.exports = nextConfig

0 commit comments

Comments
 (0)