An open API service indexing awesome lists of open source software.

https://github.com/mugilan-codes/node-devops-docker-demo


https://github.com/mugilan-codes/node-devops-docker-demo

devops docker docker-compose dockerfile droplet expressjs mongodb mongoose nginx redis

Last synced: 4 months ago
JSON representation

Awesome Lists containing this project

README

          

# node-devops-docker-demo

## Practicing Node Devops with Docker

[Devops with Docker and Node.js Youtube Playlist](https://www.youtube.com/playlist?list=PL8VzFQ8k4U1JEu7BLraz8MdKJILJir7oY)

### Resource

- [Nginx and Let’s Encrypt with Docker in Less Than 5 Minutes](https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71)
- [Setup Nginx and Let’s Encrypt with Docker](https://www.thirdrocktechkno.com/blog/setup-nginx-and-lets-encrypt-with-docker/)
- [Docker compose of nginx, express, letsencrypt SSL get 502 Bad gateway](https://stackoverflow.com/questions/57743088/docker-compose-of-nginx-express-letsencrypt-ssl-get-502-bad-gateway)

### Commands

- Build App Image

```sh
docker build -t node-devops-docker-demo-image .
```

- Run a Container (port fowarding, bind mount(read-only), and anonymous volume)

```sh
docker run -v $(pwd):/app:ro -v /app/node_modules -p 3000:4000 --env-file ./.env -d --name node-devops-docker-demo node-devops-docker-demo-image
```

- Access FileSystem

```sh
docker exec -it node-devops-docker-demo bash
```

- Exit FileSystem

```sh
exit
```

- Forcefully Remove a container with volume

```sh
docker rm node-devops-docker-demo -fv
```

- Using Docker Compose

- Build App

```sh
docker-compose up -d
```

- use this if there is a change in image (Dockerfile)

```sh
docker-compose up -d --build
```

- Delete App

```sh
docker-compose down -v
```

- Development docker-compose command

- up

```sh
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# force re-build image for changes
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build

# re-build image without downing the container and re creating anonymous volumes
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build -V

# scale the number of instances
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --scale node-app=2
```

- down

```sh
docker-compose -f docker-compose.yml -f docker-compose.dev.yml down -v

# don't remove volumes
docker-compose -f docker-compose.yml -f docker-compose.dev.yml down
```

- Production docker-compose command

- up

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# force re-build image for changes
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
```

- down

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml down -v

# don't remove volumes
docker-compose -f docker-compose.yml -f docker-compose.prod.yml down
```

- Open MongoDB directly

```sh
docker exec -it node-devops-docker-demo_mongodb_1 mongo -u "mugil" -p "mypassword"
```

**note**: Don't pass in `-v` flag to remove the volumes when using databases as it would ultimately remove all volumes, Instead start up the containers and run `docker volume prune` to remove unused volumes.

- Get network details of container

```sh
docker inspect
```

**note**: you can directly use the service name from docker-compose instead of using the ipAddress(works only for the services created/declared in docker-compose).

- Open Redis CLI

```sh
docker exec -it node-devops-docker-demo_redis_1 redis-cli
```

- View Session Keys

```sh
KEYS *
```

- Get Session Details

```sh
GET
```

### Steps to Production

- Create Ubuntu Server on Cloud Platforms like **Digital Ocean** (I am using this one), AWS, etc..
- Create a Droplet
- Copy the IP Address of the Droplet provided
- Open a terminal in your computer and SSH into the droplet

```sh
ssh root@
```

- Type in `yes` to conntinue connecting
- Type in your root password that you used while creating the droplet
- Install docker engine in the droplet

```sh
curl -fsSL https://get.docker.com -o get-docker.sh

sh get-docker.sh
```

- Install docker-compose by following instructions in the official documentation for linux

```sh
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose
```

- Set Environment Variables

```sh
export =
```

- Show all Env variables

```sh
printenv
```

- Instead of individually adding env variables, setup .env file and add the .env variables into it

```sh
vi .env
```

- Open `.profile` and add this at the bottom

```sh
vi .profile
```

```vim

set -o allexport; source /root/.env; set +o allexport
```

- Create a directory and move into it

```sh
mkdir app

cd app
```

- Clone the Git repo in this folder and pull whenever there is a change

```sh
git clone .
```

**Note**: This works with public repo. If you want to work with private repos, check [Deploy Keys](https://docs.github.com/en/developers/overview/managing-deploy-keys) section or [How to clone your private repository from GitHub to server, Droplet, VDS, etc?](https://dev.to/koddr/quick-how-to-clone-your-private-repository-from-github-to-server-droplet-vds-etc-39jm)

- Run the production docker-compose command

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# do this to see any changes made
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

# rebuild only necessary service to avoid checking other containers unneccessarily
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build node-app

# when you don't want to check for dependencies
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build --no-deps node-app

# force rebuild containers even when there is no change
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --force-recreate node-app

# force rebuild containers even when there is no change without dependecies
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --force-recreate --no-deps node-app
```

- Make requests to `http:///` routes

- Push Images to docker to avoid building images on production server. Create a repo in `dockerhub`

- Tag the local image with the name of that of the remote image

```sh
docker tag
```

- Push the tagged image to dockerhub

```sh
docker push
```

- Build the image on local machine

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml build

# build only the services that is required (custom image)
docker-compose -f docker-compose.yml -f docker-compose.prod.yml build node-app
```

- Push the custom build image to dockerhub

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml push

# push only the services that we want
docker-compose -f docker-compose.yml -f docker-compose.prod.yml push node-app
```

- Pull the latest images in the production server

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull

# only specific image
docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull node-app
```

- Update the changes in producton server

```sh
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# specific rebuild
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps node-app
```

- Use watchtower to automatically look for changes in the remote custom build image (specify the images that needs to be watched at the end)

```sh
docker run -d --name watchtower -e WATCHTOWER_TRACE=true -e WATCHTOWER_DEBUG=true -e WATCHTOWER_POLL_INTERVAL=50 -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower app_node-app_1
```

**NOTE**: No need to pull and update changes in production server if watchtower is used

- Activate docker swarm for orchestration. Get IP of the droplet by `ip add` command

```sh
docker swarm init --advertise-addr
```

- Add more manager nodes, run this command and follow the instructions

```sh
docker swarm join-token manager
```

- Add worker node to swarm

```sh
docker swarm join --token :
```

- Deploy

```sh
docker stack deploy -c docker-compose.yml -c docker-compose.prod.yml myapp
```

- check how many nodes are running

```sh
docker node ls
```

- check how many stacks are there

```sh
docker stack ls
```

- list the services in the stack

```sh
docker stack services myapp
```

- list all the services across all stacks

```sh
docker service ls
```

- list the tasks in the stack

```sh
docker stack ps myapp
```

#### TODO

- [X] Add SSL Certificate (https)

- [X] Add Domain Name

- [ ] Modify ./init-letsencrypt.sh to use docker swarm and production docker compose

- [ ] Run the modified ./init-letsencrypt.sh on the server for first time to generate fake certificates

- [ ] Everything must be automated

#### Docker Images

- [node](https://hub.docker.com/_/node)
- [mongo](https://hub.docker.com/_/mongo)
- [redis](https://hub.docker.com/_/redis)
- [nginx](https://hub.docker.com/_/nginx)

#### DOCS

- [Express behind proxies](https://expressjs.com/en/guide/behind-proxies.html)
- [Docker Script for Ubuntu](https://get.docker.com/)
- [Install Docker Compose](https://docs.docker.com/compose/install/)
- [Watchtower](https://containrrr.dev/watchtower/)
- [Docker Compose Deploy Reference](https://docs.docker.com/compose/compose-file/compose-file-v3/#deploy)