A simple webapp that connect with docker
The requiremement to start Docker
[x] Install Docker client in local pc
Do the step bellow
- Create a Dockerfile in root directory.
- Add the following code
FROM node:14
WORKDIR /app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD ["node", "app.js"]
- We selected node:14 as node version 14
- work directory /app (We can name it anything)
- copy our package.json into /app directory
- Then install all dependency in docker container
- Then copy all file into /app folder where (. means our current directory and ./ means our docker container directory)
- Then open port 3000
- Then node command (We all know what is going on by this command)
docker build . -t node-app-image
-t flag represent image name
After building docker image run following command
docker run -d --name node-app node-app-image
-d
flag represent detach mode
--name
flag represent docker container name
and next parameter docker image name
- We cannot access to 3000 port because docker will not understand local pc. It will understand local pc as outside device. To fix this problem we need to follow this step
docker run -p 8080:8080 -d --name node-app node-app-image
-p
flag represent port and first part represent our local pc which will be run in localhost:8080 and second part which is running under docker image in our express server
docker exec -it node-app bash
-it
command means intactive mode. this command will show all of the file inside docker container
The reason is to see what docker container actually doing
After any code in my local pc, we cannot see updated things in runnign port. To solve this we have to follow these
- We need to rebuild and re-run everything
But this process is messy. Every time for small changes rebuild will take time which will slow down development.
To solve this we need to sync
our local folder into docker container.
run the same command of docker run and add extra flag -v which stands for
volume
local_path:docker_path
- Here
local_path
is our local project directory. - And
docker_path
is our docker file directory which we defined/app
.
- for windows command shell use %cd%
- for windows power shell use ${pwd}
- for Mac use $(pwd)
Example: docker run -v $(pwd):/app -p 8080:8080 -d --name node-app node-app-image
that will grab current directory
If nodemon doesn't restart in docker pass -L flag
We don't want to watch node_modules
folder with docker container. But if we delete node_modules
from local directory it delete from docker container as well. To prevent this we need to follow these stese.
For this we need add another extra
volume
flag and add parameter as/app/node_modules
docker run -v $(pwd):/app -v /app/node_modules -p 8080:8080 -d --name node-app node-app-image
Now we don't want to docker to change our file. If we create any file inside docker container it impact on our local directory. So to prevent this we need to make docker container read-only
.
use same command and use extra option after docker_path name using colon (:)
docker run -v $(pwd):/app:ro -v /app/node_modules -p 8080:8080 -d --name node-app node-app-image
Example: docker run -v $(pwd):/app:ro -v /app/node_modules -e PORT=4000 -p 8080:4000 -d --name node-app node-app-image
To use Environment variable using .env file we need to follow this command along with flag --env-file
and path of the env file
Example: docker run -v $(pwd):/app:ro -v /app/node_modules --env-file ./.env -p 8080:5000 -d --name node-app node-app-image
- List all running volume
docker volume ls
- To delete all unused volume except accociated container
docker volume prune
- To delete volume along with docker container
docker rm node-app -fv
- Create a
docker-compose.yml
file add all flag in it - To get information
docker-compose up --help
- Run our app using docker compose
docker-compose up -d
Create three files
docker-compose.yml
which will be common filedocker-compose.dev.yml
which will be for developmentdocker-compose.prod.yml
which will be for production
Now update package.json
file and update scripts npm start
to node app.js
and for npm run dev
to nodemon -L app.js
So in production we don't want to install devDependencies. To do so we need to update Dockerfile
and update npm install
to some bash script
ARG NODE_ENV
RUN if [ "$NODE_ENV" = "development" ]; \
then npm install; \
else npm install --only-production;\
fi
Here we are passing ARG
NODE_ENV
which will be passed fromdocker-compose.dev.yml
anddocker-compose.prod.yml
inside build command. Add the following in docker compose file
In dev file
build:
context: .
args:
NODE_ENV: development
In prod file
build:
context: .
args:
NODE_ENV: production
pretty simple
And run this command
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
-f
flag define file where we defined 2 docker-compose file. One for common and another for production-d
flag for detach--build
which will build our docker image. without--build
docker will just restart. Image will not build
To delete docker container run same command and replace up -> down and remove
--build
flag and add-v
flag which will delete all associated volume
Note: In production we don't have any volume. so we don't need to pass -v
flag while closing container. But for development we need to pass it
Example: docker-compose -f docker-compose.yml -f docker-compose.dev.yml down -v
To setup mongo in our docker we need to get mongo
official image from docker official site
https://hub.docker.com/
use this configuration in docker-compose.yml
file
mongo:
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
volumes:
- mongo-db:/data/db
Here
image: mongo
which is docker official mongo image
we need to add environment variable asMONGO_INITDB_ROOT_USERNAME
andMONGO_INITDB_ROOT_PASSWORD
and the value is anything
Note: when we down our composer we pass -v flag which will delete all volume including mongodb. The problem is we will loose data if we delete all volumes. To prevent this we need to add volume
in docker-compose.yml
file and when we run it will throw an error. So it's simple. We need to whitelist these name volume in docker-compose.yml
in root
volumes:
mongo-db:
after that we will run our docker compose file.
When we will close our docker compose we will not pass
-v
flag which will not remove volumes. After runnign docker compose we should do the following
docker volume prune
which will remove all unused volume
const mongoose = require('mongoose');
mongoose.connect('mongodb://username:password@docker-ip-address/my_database');
To check IP address of docker run this command
docker inspect docker_mongo_1
wheredocker_mongo_1
is my mongo docker container name, for you it might be different.
Also instead of using ip address we can usemongo
as host
When we will build our docker compose we need mongo installed. So mongo needs to run first. To do this syncronously we need to pass the code bellow inside node-app container in docker-compose.yml
file
depends_on:
- mongo
To setup redis database in our docker we need to get redis
official image from docker official site
https://hub.docker.com/
Add this section under services
redis:
image: redis