Docker

Nuke docker


#!/bin/bash

printf "Stopping all containers\n"
docker ps | awk ' {print $1} ' | xargs docker kill

printf "Deleting all containers\n"
docker container ls --filter "status=exited" | awk '{ print $1 }' | xargs docker container rm

printf "Deleting all images\n"
docker image ls | awk '{print $3}' | xargs docker image rm --force

Basic config example

# docker-compose.yml
version: "3"

services:
  web:
    build: .
    # build from Dockerfile
    context: ./Path
    dockerfile: Dockerfile
    ports:
      - "5000:5000"
    volumes:
      - .:/code
  redis:
    image: redis

Common commands

# Starts existing containers for a service.
docker-compose start

# Stops running containers without removing them.
docker-compose stop

# Pauses running containers of a service.
docker-compose pause

# Unpauses paused containers of a service.
docker-compose unpause

# Lists containers.
docker-compose ps

# Builds, (re)creates, starts, and attaches to containers for a service.
docker-compose up

# Stops containers and removes containers, networks, volumes, and images created by up.
docker-compose down

Config file reference

Building

web:
  # build from Dockerfile
  build: .
  # build from custom Dockerfile
  build:
    context: ./dir
    dockerfile: Dockerfile.dev
  # build from image
  image: ubuntu
  image: ubuntu:14.04
  image: tutum/influxdb
  image: example-registry:4000/postgresql
  image: a4bc65fd

Ports

ports:
  - "3000"
  - "8000:80" # machine - port : container - port
# expose ports to linked services (not to host)
expose: ["3000"]

Commands

# command to execute
command: bundle exec thin -p 3000
command: [bundle, exec, thin, -p, 3000]

# override the entrypoint
entrypoint: /app/start.sh
entrypoint: [php, -d, vendor/bin/phpunit]

Environment variables

# environment vars
environment:
  RACK_ENV: development
environment:
  - RACK_ENV=development

# environment vars from file
env_file: .env
env_file: [.env, .development.env]

Dependencies

# makes the `db` service available as the hostname `database`
# (implies depends_on)
links:
  - db:database
  - redis

# make sure `db` is alive before starting
depends_on:
  - db

Other options

# make this service extend another
extends:
  file: common.yml # optional
  service: webapp
volumes:
  - /var/lib/mysql
  - ./_data:/var/lib/mysql

Advanced features

Labels

services:
  web:
    labels:
      com.example.description: "Accounting web app"

DNS servers

services:
  web:
    dns: 8.8.8.8
    dns:
      - 8.8.8.8
      - 8.8.4.4

Devices

services:
  web:
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"
services:
  web:
    external_links:
      - redis_1
      - project_db_1:mysql

Hosts

services:
  web:
    extra_hosts:
      - "somehost:192.168.1.100"

Network

# creates a custom network called `frontend`
networks:
  frontend:

External network

# join a preexisting network
networks:
  default:
    external:
      name: frontend

Problmes with UFW on VPS?

Well this comes with experience iguess. I once disabled all traffic, but the ssh and https using UFW ,but did not know that docker fucks up iptables and bypasses ufw. So I left the database open...

So there is thankfully a workadound,

basically add this segment to file /etc/ufw/after.rules.

# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward

-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16

-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN

-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12

-A DOCKER-USER -j RETURN

-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP

COMMIT
# END UFW AND DOCKER

Best flag for debugging dockerfile

docker compose --verbose up --build But do not fuck up the order of the arguments!

Composing dockerfiles

Postgres dockerfile with init script

FROM postgres:16.1-bookworm

COPY scripts/* /docker-entrypoint-initdb.d/
  postgres:
    build:
      context: postgres
      dockerfile: Dockerfile
    env_file:
      - .postgres.env
    volumes:
      - ./data/pgdata:/var/lib/postgresql/data

file: .postgres.env

POSTGRES_DB=postgresdb
POSTGRES_USER=postgresuser
POSTGRES_PASSWORD=postgrespass

Mysql dockerfile with init script

FROM mysql:8.0.31

ADD ./scripts/* /docker-entrypoint-initdb.d/
  mysql:
    image: mysql:8.2.0
    env_file:
      - .mysql.env
    volumes:
      - ./data/mysql:/var/lib/mysql

file: .mysql.env

MYSQL_DATABASE=mysqldb
MYSQL_USER=mysqluser
MYSQL_PASSWORD=mysqlpass
MYSQL_ROOT_PASSWORD=mysqlpass

Containerize a script

FROM python:3.10-bookworm

WORKDIR /app

COPY requirements.txt .

RUN python -m venv $VENV_PATH
ENV PATH="$VENV_PATH/bin:$PATH"

RUN pip install --no-cache-dir -r requirements.txt

COPY main.py .

CMD ["bash", "-c", "while true; do python main.py; sleep 30; done"]
  pythonml:
    build:
      context: pythonml
      dockerfile: Dockerfile
    volumes:
      - ./data/pythonml:/app/predictions
    environment:
      - POSTGRES_HOST=postgres
      - MYSQL_HOST=mysql
    env_file:
      - .postgres.env
      - .mysql.env
    depends_on:
      - postgres
      - mysql

Jupyter notebook

FROM python:3.11.1-bullseye

ENV JUPYTER_DIR=/jupyter-data
ENV JUPYTER_PASSWORD=supersecurepassword
ENV VENV_PATH=/opt/venv

RUN python -m venv $VENV_PATH
ENV PATH="$VENV_PATH/bin:$PATH"

RUN pip install mysql-connector-python==8.0.31 jupyter==1.0.0 pandas==1.5.2

EXPOSE 8888

ENTRYPOINT jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --NotebookApp.token=${JUPYTER_PASSWORD} --allow-root --notebook-dir=${JUPYTER_DIR}
  jupyter:
    build:
      context: ./jupyter
    ports:
      - 666:8888
    environment:
      - JUPYTER_DIR=/jupyter-data
      - JUPYTER_PASSWORD=bejba123
    volumes:
      - ./notebooks:/jupyter-data
    networks:
      - ids-network