Skip to content

Commit fa50036

Browse files
committed
Updated readme file
1 parent ea3aeb5 commit fa50036

File tree

3 files changed

+152
-6
lines changed

3 files changed

+152
-6
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ POSTGRES_USER=john_doe
22
POSTGRES_PASSWORD=john.doe
33
POSTGRES_DB=docker_test_db
44
DATABASE_URL=postgresql://john_doe:john.doe@postgres:5432/docker_test_db?schema=public
5-
PORT=8000
5+
SERVER_PORT=8000
66
VITE_SERVER_URL=http://127.0.0.1:7999

Readme.md

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,153 @@
1-
### Docker Tutorial
1+
### Docker Compose for a Full Stack Application
22

33
This repository demonstrates how to set up a React JS, Node JS server with a PostgreSQL database server inside docker containers and connect them all together
44

5-
### Setting up the server
5+
#### TL;DR
6+
7+
To get this project up and running, follow these steps
8+
9+
1. Make sure you have Docker installed in your system. For installation steps, follow the following steps:
10+
1. For **[Mac](https://docs.docker.com/desktop/install/mac-install/)**
11+
2. For **[Ubuntu](https://docs.docker.com/engine/install/ubuntu/)**
12+
3. For **[Windows](https://docs.docker.com/desktop/install/linux-install/)**
13+
2. Clone the repository into your device
14+
3. Open a terminal from the cloned project's directory (Where the `docker-compose.yml` file is present)
15+
4. Run the command: `docker compose up`
16+
17+
That's all! That should get the project up and running. To see the output, you can access `http://127.0.0.1:4172` from the browser and you should find a web page with a list of users. This entire system with the client, server & database are running inside of docker and being accessible from your machine.
18+
19+
Here is a detailed explanation on what is going on.
20+
21+
#### **1. Introduction**
22+
23+
[Docker](https://docs.docker.com/) at its core is a platform as a service that uses OS-level virtualization to deploy/deliver software in packages called containers. It is done for various advantages, such as cross platform consistency and flexibility and scalability.
24+
25+
[Docker Compose](https://docs.docker.com/compose/) is a tool for defining and running multi-container applications. It is the key to unlocking a streamlined and efficient development and deployment experience.
26+
27+
#### **2. Using Docker and Docker Compose**
28+
29+
When it comes to working with Full Stack Applications, i.e. ones that will involve more than one set of technology to integrate it into one fully fledged systen, Docker can be fairly overwhelming to configure from scratch. It is not made any easier by the fact that there are various types of environment dependencies for each particular technology, and it only leads to the risk of errors at a deployment level.
30+
31+
**Note:** The `.env` file adjacent in the directory with `docker-compose.yml` will contain certain variables that will be used in the docker compose file. They will be accessed whenever the `${<VARIABLE_NAME>}` notation is used.
32+
33+
This example will work with PostgreSQL as the database, a very minimal Node/Express JS server and React JS as the client side application.
34+
35+
#### **3. Individual Containers**
36+
37+
The following section goes into a breakdown of how the `docker-compose.yml` file works with the individual `Dockerfile`. Let's take a look at the docker-compose file first. We have a key called `services` at the very top, which defines the different applications/services we want to get running. As this is a `.yml` file, it is important to remember that indentations are crucial. Lets dive into the first service defined in this docker compose file, the database.
38+
39+
##### **1. Database**
40+
First of all, the database needs to be set up and running in order for the server to be able to connect to it. The database does not need any Dockerfile in this particular instance, however, it can be done with a Dockerfile too. Lets go through the configurations.
41+
42+
*`docker-compose.yml`*
43+
```yml
44+
postgres:
45+
container_name: database
46+
ports:
47+
- "5431:5432"
48+
image: postgres
49+
environment:
50+
POSTGRES_USER: "${POSTGRES_USER}"
51+
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
52+
POSTGRES_DB: ${POSTGRES_DB}
53+
volumes:
54+
- ./docker_test_db:/var/lib/postgresql/data
55+
healthcheck:
56+
test: ["CMD-SHELL", "sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'"]
57+
interval: 5s
58+
timeout: 60s
59+
retries: 5
60+
start_period: 80s
61+
```
62+
#### Explanation
63+
- ***postgres***: used to identify the service that the section of the compose file is for
64+
- ***container_name***: the name of the service/container that we have chosen
65+
- ***ports***: maps the host port (making it accessible from outside) to the port being used by the application in Docker.
66+
- ***image***: defines the Docker image that will be required to make this container functional and running
67+
- ***environment***: defined variables for the environment of this particular service. For example, for this PostgreSQL service, we will be defining a `POSTGRES_USER`,`POSTGRES_PASSWORD` and `POSTGRES_DB`. They're all being assigned with the values in the `.env`.
68+
- ***volumes***: This particular key is for we want to create a container that can **_persist_** data. This means that ordinarily, when a Docker container goes down, so does any updated data on it. Using volumes, we are mapping a particular directory of our local machine with a directory of the container. In this case, that's the directory where postgres is reading the data from for this database.
69+
- ***heathcheck***: when required, certain services will need to check if their state is functional or not. For example, PostgreSQL, has a behavior of turning itself on and off a few instances at launch, before finally being functional. For this reason, healthcheck allows Docker Compose to allow other services to know when it is fully functional.
70+
The few properties below healthcheck are doing the following:
71+
- ***test***: runs particular commands for the service to run checks
72+
- ***interval***: amount of time docker compose will wait before running a check again
73+
- ***timeout***: amount of time that the a single check will go on for, before it times out without any response or fails
74+
- ***retries***: total number of tries that docker compose will try to get the healthcheck for a positive response, otherwise fail and declare it as a failed check
75+
- ***start_period***: specifies the amount of time to wait before starting health checks
76+
77+
##### **2. Server**
78+
79+
*`Dockerfile`*
80+
```Dockerfile
81+
FROM node:18
82+
WORKDIR /server
83+
COPY src/ /server/src
84+
COPY prisma/ /server/prisma
85+
COPY package.json /server
86+
RUN npm install
87+
RUN npx prisma generate
88+
```
89+
**Explanation**
90+
***FROM*** - tells Docker what image is going to be required to build the container. For this example, its the Node JS (version 18)
91+
***WORKDIR*** - sets the current working directory for subsequent instructions in the Dockerfile. The `server` directory will be created for this container in Docker's environment
92+
***COPY*** - separated by a space, this command tells Docker to copy files/folders ***from local environment to the Docker environment***. The code above is saying that all the contents in the src and prisma folders need to be copied to the `/server/src` & `/srver/prisma` folders in Docker, and package.json to be copied to the `server` directory's root.
93+
***RUN*** - executes commands in the terminal. The commands in the code above will install the necessary node modules, and also generate a prisma client for interacting with the database (it will be needed for seeding the database initially).
94+
95+
*`docker-compose.yml`*
96+
```yml
97+
server:
98+
container_name: server
99+
build:
100+
context: ./server
101+
dockerfile: Dockerfile
102+
ports:
103+
- "7999:8000"
104+
command: bash -c "npx prisma migrate reset --force && npm start"
105+
environment:
106+
DATABASE_URL: "${DATABASE_URL}"
107+
PORT: "${SERVER_PORT}"
108+
depends_on:
109+
postgres:
110+
condition: service_healthy
111+
```
112+
**Explanation**
113+
***build***: defines the build context for the container. This can contain steps to build the container, or contain path to Dockerfiles that have the instructions written. The ***context*** key directs the path, and the ***dockerfile*** key contains the name of the Dockerfile.
114+
***command***: executes commands according to the instructions that are given. This particular command is executed to first make migrations to the database and seed it, and then start the server.
115+
***environment***: contains the key-value pairs for the environment, which are available in the .env file at the root directory. `DATABASE_URL` and `PORT` both contain corresponding values in the .env file.
116+
***depends_on***: checks if the dependent container is up, running and functional or not. This has various properties, but in this example, it is checking if the `service_healthy` flag of our postgres container is up and functional or not. The `server` container will only start if this flag is returned being `true` from the ***healthcheck*** from the PostgreSQL
117+
118+
##### **3. Client**
119+
120+
*`Dockerfile`*
121+
```Dockerfile
122+
FROM node:18
123+
ARG VITE_SERVER_URL=http://127.0.0.1:7999
124+
ENV VITE_SERVER_URL=$VITE_SERVER_URL
125+
WORKDIR /client
126+
COPY public/ /client/public
127+
COPY src/ /client/src
128+
COPY index.html /client/
129+
COPY package.json /client/
130+
COPY vite.config.js /client/
131+
RUN npm install
132+
RUN npm run build
133+
```
134+
**Explanation**
135+
Note: *The commands for `client` are very similar to the already explained above for `server`*
136+
***ARG***: defines a variable that is later passed to the ***ENV*** instruction
137+
***ENV***: Assigns a key value pair into the context of the Docker environment for the container to run. This essentially contains the domain of the API that will be fired from the client later.
138+
139+
*`docker-compose.yml`*
140+
```yml
141+
client:
142+
container_name: client
143+
build:
144+
context: ./client
145+
dockerfile: Dockerfile
146+
command: bash -c "npm run preview"
147+
ports:
148+
- "4172:4173"
149+
depends_on:
150+
- server
151+
```
152+
**Explanation**
153+
Note: *The commands for `client` are very similar to the already explained above for `server` and `postgres`*

server/Dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
FROM node:18
2-
# ARG DATABASE_URL="postgresql://john_doe:john.doe@postgres:5432/docker_test_db?schema=public"
3-
# ENV DATABASE_URL=$DATABASE_URL
42
WORKDIR /server
53
COPY src/ /server/src
64
COPY prisma/ /server/prisma
7-
COPY package.json /server/
5+
COPY package.json /server
86
RUN npm install
97
RUN npx prisma generate

0 commit comments

Comments
 (0)