Skip to content

Instantly share code, notes, and snippets.

@mkuchak
Last active December 22, 2022 21:46
Show Gist options
  • Save mkuchak/b3afde402620781d3b79b457cbacc7a5 to your computer and use it in GitHub Desktop.
Save mkuchak/b3afde402620781d3b79b457cbacc7a5 to your computer and use it in GitHub Desktop.
Manage Docker for development and production environment

Change DNS Docker

Create a /etc/docker/daemon.json file with this content:

{
  "dns": ["8.8.8.8", "8.8.4.4"]
}

And restart the docker service:

sudo service docker restart

1. Docker Setup

1.1. Docker aliases on .bashrc or .zshrc

alias dc="sudo docker-compose"
alias d="sudo docker"
alias dps='sudo docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}\t{{.Image}}"'

If you don't want to use sudo, follow this tutorial and remove it from the aliases (recommended)

1.2. General commands

Handle images, containers, volumes and networks

# Handle images
d image ls -a
d image rm -f <image>

# Handle containers
d container ls -a
d container rm -fv <container>
d start <container>
d restart <container>
d stop <container>
d inspect <container>
d logs -f <container>

# Handle volumes
d volume ls
docker volume rm <volume>

# Handle networks
d network ls
d network rm <network>

Handle bulk Docker

# Removing all unused docker objects
d system prune -fa --volumes; # reset docker
d container prune -f;
d volume prune -f;
d network prune -f;
d image prune -fa;

# Stop all containers
d stop $(d ps -aq);

# Delete all containers
d rm -f $(d ps -aq);

# Delete all volumes
d volume rm -f $(d volume ls -q);

# Delete all networks
d network rm $(d network ls -q)

# Delete all images
d rmi -f $(d images -q);

2. Docker Development

2.1. Ubuntu

Run Ubuntu container to develop all applications. Install Remote - Containers extension from Microsoft in VSCode to use this container to develop.

2.1.1. Running standard container

# Start a fixed development container from latest Ubuntu and run a standard setup script
d run -it --init --name ubuntu \
  -v ~/Workspaces:/home/Workspaces \
  -w /home/Workspaces \
  -e LANG=en_US.UTF-8  \
  --network host \
  --restart=unless-stopped \
  -d ubuntu:rolling bash \
  -c "apt update -y; apt upgrade -y; \
  apt install -y curl; \
  curl -fsSL https://git.io/Ju5dA | bash -; \
  bash"

# Enter dev container to use console
d exec -it ubuntu bash

The shell script URL can be shorten here.

2.2. Node.js

Some tips and best practices for Node.js + Docker

2.2.1. Running standard container

# Start temporary development container
d run --rm -it --name node-dev-temp \
  -v $PWD:/home/app -w /home/app \
  -p 3000:3000 node:latest bash \
  -c "apt update -y; apt upgrade -y; clear; bash"

# Alternative flags
--env-file ./.env
--user node
--memory "300M"
--memory-swap "1G"

# Start fixed development container from a fixed node version
d run -it --init --name node-dev-14 \
  -v ~/Workspaces:/home/Workspaces \
  -w /home/Workspaces \
  -p 3000:3000 \
  --restart=unless-stopped \
  -d node:14 bash \
  -c "apt update -y; apt upgrade -y; bash"

# Enter dev container to use console
d exec -it node-dev-14 bash

2.2.2. Creating custom image

Dockerfile

FROM node:14
WORKDIR /home/app
COPY package.json .
RUN npm install
COPY . ./
CMD ["npm", "run", "dev"]

.dockerignore

node_modules
Dockerfile
docker-compose*
.dockerignore
.git
.gitignore

Commands

# Build app image
d build -t node-app-image .

# Run container based on the image
d run --name node-app \
  -v $PWD:/home/app:ro \
  -v /home/app/node_modules \
  --env-file ./.env -p 3000:3000 \
  -d node-app-image

# Enter container to use console
d exec -it node-app bash

2.2.3. Automating with docker-compose

Docker-compose version specifications to choose the features you want

docker-compose.yml

version: "3"
services:
  node-app:
    build: .
    ports:
      - 3000:3000
    volumes:
      - .:/home/app
      - /home/app/node_modules
    env_file:
      - ./.env
    # environment:
    #   - PORT=3000

Commands

# Start and stop
dc up -d
dc down -v --remove-orphans

# Rebuild
dc up -d --build --force-recreate --remove-orphans -V

# Down + Start + Enter/Logs
dc down --remove-orphans -v && time dc up -d --build -V
dc down --remove-orphans -v && dc up -d --build -V && d exec -it nextjs-client bash
dc down --remove-orphans -v && dc up -d --build -V && d logs -f nextjs-client

# Specific docker-compose file
dc -f docker-compose.test.yml up -d --build -V
dc -f docker-compose.test.yml down --remove-orphans -v

2.3. Databases

2.3.1. Install

Don't forget to change PGADMIN_DEFAULT_EMAIL=root@root.com to your e-mail in pgAdmin

# MariaDB
d run --name mariadb \
  -e MYSQL_ROOT_PASSWORD=root \
  --network host \
  --restart=unless-stopped \
  -d mariadb:latest

# Postgres
d run --name postgres \
  -e POSTGRES_USER=root \
  -e POSTGRES_PASSWORD=root \
  --network host \
  --restart=unless-stopped \
  -d postgres:latest

# Mongo
d run --name mongo \
  -e MONGO_INITDB_ROOT_USERNAME=root \
  -e MONGO_INITDB_ROOT_PASSWORD=root \
  --network host \
  --restart=unless-stopped \
  -d mongo:latest

# Redis
d run --name redis \
  --network host \
  --restart=unless-stopped \
  -d redis:latest \
  redis-server --save 60 1

# phpMyAdmin
d container create --name phpmyadmin \
  -e PMA_ARBITRARY=1 \
  -e MEMORY_LIMIT=1024M \
  -e UPLOAD_LIMIT=1024M \
  --network host \
  phpmyadmin:latest

# pgAdmin
d container create --name pgadmin \
  -e PGADMIN_DEFAULT_EMAIL=root@root.com \
  -e PGADMIN_DEFAULT_PASSWORD=root \
  --network host \
  dpage/pgadmin4:latest

# Mongo Express
d container create --name mongo-express \
  -e ME_CONFIG_MONGODB_SERVER=localhost \
  -e ME_CONFIG_MONGODB_ADMINPASSWORD=root \
  -e ME_CONFIG_MONGODB_ADMINUSERNAME=root \
  -e VCAP_APP_PORT=80 \
  --network host \
  mongo-express:latest

# RabbitMQ
d run --rm -it --name some-rabbit \
  --hostname my-rabbit \
  -e RABBITMQ_DEFAULT_USER=user \
  -e RABBITMQ_DEFAULT_PASS=password \
  -p 15672:15672 \
  -p 5672:5672 \
  rabbitmq:3-management

Start/stop the admin wanted, one at a time (all them works on port 80)

d start phpmyadmin
d start pgadmin
d start mongo-express

You also can create a database network and can fix the IP from containers, but don't forget to expose the ports

d network create db --subnet 172.88.0.0/16

2.3.2. Access Databases in browser

Database Admin IP:Port Access
MariaDB phpMyAdmin localhost:3306 http://localhost
Postgres pgAdmin localhost:5432 http://localhost
Mongo Mongo Express localhost:27017 http://localhost

3. Docker Production

https://docs.docker.com/language/nodejs/configure-ci-cd/

3.1. Node.js

3.1.1. Development and production with docker-compose

Dockerfile

FROM node:14
WORKDIR /home/app
COPY package.json .

ARG NODE_ENV
RUN if [ "$NODE_ENV" = "development" ]; \
    then npm install; \
    else npm install --only=production; \
    fi

COPY . ./
CMD ["npm", "run", "start"]

docker-compose.dev.yml

version: "3"
services:
  app:
    build:
      context: .
      args:
        NODE_ENV: development
    restart: always
    ports:
      - 3000:3000
    volumes:
      - .:/home/app
      - /home/app/node_modules
    networks:
      app_network:
        ipv4_address: 172.28.0.2
    environment: 
      - PORT=3000
      - NODE_ENV=development
      - MONGO_USER=root
      - MONGO_PASS=root
      - MONGO_DB=app-dev
    command: npm run dev
    depends_on:
      - db

  db:
    image: mongo
    restart: always
    volumes:
      - db_data:/data/db
    networks:
      app_network:
        ipv4_address: 172.28.0.3
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=root

  dba:
    image: mongo-express
    restart: always
    ports:
      - 3001:8081
    networks:
      app_network:
        ipv4_address: 172.28.0.4
    environment:
      - ME_CONFIG_MONGODB_SERVER=db
      - ME_CONFIG_MONGODB_ADMINUSERNAME=root
      - ME_CONFIG_MONGODB_ADMINPASSWORD=root
    depends_on:
      - db

volumes:
  db_data:

networks:
  app_network:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

docker-compose.prod.yml

version: "3"
services:
  app:
    build:
      context: .
      args:
        NODE_ENV: production
    ports:
      - 3000:3000
    volumes:
      - .:/home/app
      - /home/app/node_modules
    environment: 
      - PORT=3000
      - NODE_ENV=production
      - MONGO_USER=root
      - MONGO_PASS=root
      - MONGO_DB=app-prod
    command: npm run start
    depends_on:
      - db
  
  db:
    image: mongo
    volumes:
      - mongo_data:/data/db
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=root

volumes:
  mongo_data:

Commands

# Run default config file and overlap using dev/prod config
dc -f docker-compose.dev.yml up -d --build --force-recreate --remove-orphans -V
dc -f docker-compose.prod.yml up -d --build --force-recreate --remove-orphans -V

4. Draft

# Docker hub push
d tag 706ec967bf1e abc/ansible:v1

# Docker hub push
d push abc/ansible:v1
# Linux Essential Setup
apt install -y locales sudo git htop nano;
locale-gen en_US.UTF-8;
# Node.js Setup
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -;
apt install -y nodejs yarn;
# ZSH Setup
apt install zsh -y;
yes | sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)";
yes n | sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zinit/master/doc/install.sh)";
git clone https://github.com/denysdovhan/spaceship-prompt.git "/root/.oh-my-zsh/themes/spaceship-prompt" --depth=1;
ln -s "/root/.oh-my-zsh/themes/spaceship-prompt/spaceship.zsh-theme" "/root/.oh-my-zsh/themes/spaceship.zsh-theme";
zsh;
awk '{sub(/robbyrussell/,"spaceship")}1' ~/.zshrc > ~/.temp;
mv ~/.temp ~/.zshrc;
echo "\n# Plugins\nzinit light zsh-users/zsh-autosuggestions\nzinit light zsh-users/zsh-completions\nzinit light zdharma/fast-syntax-highlighting\n\n# Theme\nLS_COLORS=\$LS_COLORS:'ow=01;34:' ; export LS_COLORS\n\nSPACESHIP_PROMPT_ORDER=(\n user # Username section\n dir # Current directory section\n host # Hostname section\n git # Git section (git_branch + git_status)\n hg # Mercurial section (hg_branch + hg_status)\n exec_time # Execution time\n line_sep # Line break\n vi_mode # Vi-mode indicator\n jobs # Background jobs indicator\n exit_code # Exit code section\n char # Prompt character\n)\n\nSPACESHIP_USER_SHOW='always' # Shows System user name before directory name\n\nSPACESHIP_PROMPT_ADD_NEWLINE=false\n# SPACESHIP_PROMPT_SEPARATE_LINE=false # Make the prompt span across two lines\n# SPACESHIP_DIR_TRUNC=1 # Shows only the last directory folder name\n\nSPACESHIP_CHAR_SYMBOL='>'\nSPACESHIP_CHAR_SUFFIX=' '\n\n# Hide % on start\nunsetopt PROMPT_SP\n" >> ~/.zshrc;
echo "\nexec zsh" >> ~/.bashrc;
# Sugar Git Setup
git clone https://github.com/mkuchak/sugar-git /root/.sugar-git;
cd /root/.sugar-git;
bash /root/.sugar-git/install.sh;
git config --global core.editor "code --wait";
# Personal Configs
echo "\n# WSL fix terminal ctrl\nbindkey -e\nbindkey '^H' backward-kill-word # Control + backspace\nbindkey ';5C' forward-word # Control + arrows\nbindkey ';5D' backward-word\n\n# Linux aliases\nalias ws='cd /home/Workspaces'\nalias dot='setopt -s glob_dots'\nalias ll='ls -lah'\nalias ssh='ssh -o ServerAliveInterval=60'\nalias ssh-reset='ssh-keygen -R'\n" >> ~/.zshrc;
# Reload ZSH
source ~/.zshrc;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment