Skip to content

Commit

Permalink
Add docker
Browse files Browse the repository at this point in the history
  • Loading branch information
IgorBayerl committed Mar 10, 2024
1 parent 2367bf1 commit beedd69
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.git
.gitignore
*.md
dist
52 changes: 51 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,61 @@ Before starting, ensure you have the following installed:
```


## Docker

**Happy coding!**
### Development

To run the application in a development environment using Docker, follow these steps:

1. **Ensure Docker is Installed**

Before proceeding, make sure Docker is installed on your machine. You can download it from [Docker's official website](https://www.docker.com/get-started).
2. **Start the Development Environment**
Use the following command in the root of the project directory to start the development environment:
```bash
docker-compose -f docker-compose.yaml up --build
```
This command builds and starts both the `client` and `server` services as defined in `docker-compose.yaml`. It mounts the source code into the container to enable live reloading, so any changes you make to the source code will automatically reflect in the running containers.
### Production
To run the application in a production environment using Docker, you will use a different Docker Compose file that is optimized for production:
1. **Ensure Docker is Installed**
If not already done, make sure Docker is installed on your machine.
2. **Start the Production Environment**
Use the following command in the root of the project directory to start the production environment:
```bash
docker-compose -f docker-compose.prod.yaml up --build
```
This command uses `docker-compose.prod.yaml`, which is configured to build and run the `client` and `server` using their respective production Dockerfiles (`Dockerfile.prod`). Unlike the development environment, the production setup does not mount the source code into the container. Instead, it builds static assets and runs the optimized version of your application.
**Note:** It's important to ensure that your production Dockerfiles (`Dockerfile.prod` for both client and server) are properly configured to build your application for production. This includes installing dependencies, building your Next.js application for the client, and setting up any necessary production configurations for your server.

---

### Additional Notes

- **Docker Compose Files**: The project includes two Docker Compose files:
- `docker-compose.yaml` for development.
- `docker-compose.prod.yaml` for production.
- **Live Reloading**: In development, the application is set up to support live reloading. This means you can edit your code, and the changes will automatically reflect in the running containers without needing to rebuild them.


---
**Happy coding!**



## Game Flow Diagram

![Game Flow Diagram](./docs/game_flow.svg)
36 changes: 36 additions & 0 deletions client/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Starting with Node.js 18 Alpine for a lightweight image
FROM node:20-alpine AS client

# Enable Corepack to use PNPM
RUN corepack enable

# Set the working directory in the Docker container
WORKDIR /app

# Copy the necessary files to install dependencies
# Including the pnpm-lock.yaml at the root to respect monorepo dependency resolutions
COPY pnpm-lock.yaml* ./
COPY package.json ./

# Copy the entire monorepo to properly resolve internal dependencies like `types`
# Note: This might include more than necessary for just the client build, but it ensures
# that pnpm can correctly link local packages. Adjustments may be needed based on your exact structure.
COPY . .

# Install dependencies using PNPM, ensuring to work within the context of a monorepo
RUN pnpm install --frozen-lockfile


# Copying the rest of the client application files might not be necessary if you've already copied the entire monorepo
# However, if you adjust to be more selective in what you copy to the Docker context (for efficiency),
# ensure all necessary files for your client application are copied here.

# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry
# Uncomment the following line to disable telemetry during runtime
# ENV NEXT_TELEMETRY_DISABLED 1

# The port that your Next.js app will run on (default is 3000)
EXPOSE 3000

# Start the Next.js development server
CMD ["pnpm", "dev-client"]
34 changes: 34 additions & 0 deletions client/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Start with Node.js 20 Alpine for a lightweight image
FROM node:20-alpine AS client

# Set the working directory in the Docker container
WORKDIR /app

# Enable Corepack to use PNPM
RUN corepack enable

# Copy the pnpm lock file and other necessary files for dependency installation
COPY pnpm-lock.yaml* package.json ./

# Copy the entire monorepo to properly resolve internal dependencies
COPY . .

# Install dependencies using PNPM
RUN pnpm install --frozen-lockfile

# Add ARG directives for environment variables
ARG NEXT_PUBLIC_GAME_SOCKET_SERVER
ARG NEXT_PUBLIC_GAME_SERVER

# Use the environment variables for the build
ENV NEXT_PUBLIC_GAME_SOCKET_SERVER=$NEXT_PUBLIC_GAME_SOCKET_SERVER
ENV NEXT_PUBLIC_GAME_SERVER=$NEXT_PUBLIC_GAME_SERVER

# Build the Next.js application
RUN pnpm build-client

# The command to run your app in production mode
CMD ["pnpm", "start-client"]

# Expose the port your app runs on
EXPOSE 3000
22 changes: 22 additions & 0 deletions docker-compose.prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '3.8'
services:
server:
build:
context: .
dockerfile: server/Dockerfile.prod
ports:
- "2567:2567"
environment:
- NODE_ENV=production
# The client will probably be deployed on a Vercel server
client:
build:
context: .
dockerfile: client/Dockerfile.prod
args:
- NEXT_PUBLIC_GAME_SOCKET_SERVER=ws://localhost:2567
- NEXT_PUBLIC_GAME_SERVER=http://localhost:2567
ports:
- "3000:3000"
environment:
- NODE_ENV=production
28 changes: 28 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
version: '3.8'
services:
server:
build:
context: .
dockerfile: server/Dockerfile
ports:
- "2567:2567"
volumes:
- .:/app
- /app/node_modules
- /app/server/node_modules
environment:
- NODE_ENV=development
client:
build:
context: .
dockerfile: client/Dockerfile
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
- /app/client/node_modules
environment:
- NODE_ENV=development
- NEXT_PUBLIC_GAME_SOCKET_SERVER=ws://localhost:2567
- NEXT_PUBLIC_GAME_SERVER=http://localhost:2567
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
"scripts": {
"dev-server": "pnpm --filter server dev",
"dev-client": "pnpm --filter client dev",
"dev": "npm-run-all --parallel dev-server dev-client",
"start-server": "pnpm --filter server start",
"build-client": "pnpm --filter client build",
"dev": "npm-run-all --parallel dev-server dev-client"
"start-client": "pnpm --filter client start"
},
"devDependencies": {
"npm-run-all": "^4.1.5"
Expand Down
21 changes: 21 additions & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Base image with Node.js and PNPM
FROM node:20-slim AS server
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

# Install OpenSSL
RUN apt-get update -y && apt-get install -y openssl libssl-dev

# Copy the entire monorepo
COPY . /app
WORKDIR /app

# Install dependencies for the entire workspace
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

# Expose the port the server runs on
EXPOSE 2567

# Start the server using the pnpm start script
CMD ["pnpm", "dev-server"]
24 changes: 24 additions & 0 deletions server/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Base image with Node.js and PNPM
FROM node:20-slim AS server
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

# Install OpenSSL
RUN apt-get update -y && apt-get install -y openssl libssl-dev

# Copy the entire monorepo
COPY . /app
WORKDIR /app

# Install dependencies for the entire workspace
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

# Set the working directory to the server package
WORKDIR /app/server

# Expose the port the server runs on
EXPOSE 2567

# Start the server using the pnpm start script
CMD ["pnpm", "start"]
8 changes: 3 additions & 5 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
"private": true,
"name": "@ccc-cards-game/server",
"version": "1.0.0",
"description": "npm init template for bootstrapping an empty Colyseus project",
"main": "build/index.js",
"description": "Server for the a multiplayer game of Cards Against Humanity",
"main": "src/index.ts",
"engines": {
"node": ">= 16.13.0"
},
"scripts": {
"prepare": "pnpm prisma generate",
"dev": "tsx watch src/index.ts",
"loadtest": "tsx loadtest/example.ts --room my_room --numClients 2",
"build": "npm run clean && tsc",
"clean": "rimraf build",
"test": "vitest",
"coverage": "vitest run --coverage",
"start": "tsx watch src/index.ts",
Expand All @@ -23,7 +21,7 @@
"lint:fix": "eslint --fix .",
"prettier": "prettier --write ."
},
"author": "",
"author": "Igor Bayerl",
"license": "UNLICENSED",
"bugs": {
"url": "https://github.com/colyseus/create-colyseus/issues"
Expand Down
24 changes: 16 additions & 8 deletions server/src/routes/deckRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,40 @@ router.post(
router.post(
"/questions/new",
asyncHandler(async (req: Request, res: Response) => {
const validatedData: TQuestion = await zParse(QuestionSchema, req.body);
const validatedData: Omit<TQuestion, "deckId"> = await zParse(QuestionSchema, req.body);
const newQuestion = await db.question.create({
data: validatedData,
data: {
...validatedData,
deckId: req.body.deckId
}
});
res.status(201).json({
message: "Question created successfully",
data: newQuestion,
data: newQuestion
});
}),
})
);


// Endpoint to add a new Answer
router.post(
"/answers/new",
asyncHandler(async (req: Request, res: Response) => {
const validatedData: TAnswer = await zParse(AnswerSchema, req.body);
const validatedData: Omit<TAnswer, "deckId"> = await zParse(AnswerSchema, req.body);
const newAnswer = await db.answer.create({
data: validatedData,
data: {
...validatedData,
deckId: req.body.deckId
}
});
res.status(201).json({
message: "Answer created successfully",
data: newAnswer,
data: newAnswer
});
}),
})
);


// Endpoint to add a new Deck
router.post(
"/decks/new",
Expand Down

0 comments on commit beedd69

Please sign in to comment.