Containers

Containers

Matt Loberg

  • Principal Software Engineer @ The Nerdery
  • Twitter - @mloberg
  • Website - mlo.io

WTF is a Container?

It's a Virtual Machine

But not really

Why containers?

Consistently Run Anywhere

Isolation

Lightweight

Speed To Market

Docker

Hello World!

Docker Run Hello-World

docker run hello-world

🤔

Docker Hub

Docker Run Hello-Nginx

docker run --detach \
    --publish 8080:80 \
    kitematic/hello-world-nginx
docker run -it php:7.1-cli

Tags

docker ps

Kitematic

Portainer

Docker Commands

  • docker stop
  • docker rm
  • docker start
  • docker logs

Questions?

dockerfile

Dockerfile

  • FROM - Starting point
  • COPY - Copy files
  • WORKDIR - Working directory of the container
  • EXPOSE - Ports exposed on container
  • CMD - Command to run in the container
FROM php:7.2

COPY . /app

WORKDIR /app

EXPOSE 8000

CMD [ "php", "-S", "0.0.0.0:8000", "-t", "public" ]

Docker build

docker run --rm --detach \
    --publish 8080:8000 \
    mlo/mnphp-container:builtin

More Dockerfile

  • New base image
  • RUN - Run commands on container
  • No CMD, inherits from base image
  • Clean up apt to keep image size small
  • Caches layers
  • Group commands to not leave around excess data in layers
FROM php:7.2-apache

# PHP extensions
RUN apt-get update \
    && apt-get install -y zlib1g-dev libicu-dev git curl \
    && rm -rf /var/lib/apt/lists/* \
    && docker-php-ext-install pdo_mysql \
    && docker-php-ext-install intl \
    && docker-php-ext-install zip \
    && apt-get purge --auto-remove -y

# Apache configuration
COPY docker/apache/vhost.conf /etc/apache2/sites-enabled/000-default.conf

# Add the application
COPY . /app

Composing Your Application

Composing Your Application

Docker Compose

  • Entire application defined in YAML
  • Services (containers)
  • Networks
  • Volumes
  • Deployments
version: "3.6"

services:
  php-fpm:
    build: docker/php-fpm
    working_dir: /app
    volumes:
      - ./:/app:cached
  nginx:
    image: nginx:alpine
    volumes:
      - ./:/app:cached
      - ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
    ports:
      - 8000:80
  mysql:
    image: mysql:5.6
    environment:
      MYSQL_DATABASE: test
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - dbdata:/var/lib/mysql
  redis:
    image: redis:alpine
  mailhog:
    image: mailhog/mailhog:latest
    ports:
      - 8025:8025

volumes:
  dbdata:

Docker Compose Up

DEMO

To Production & Beyond

Container orchestration

Kubernetes

Anti-Patterns

Not Using Official Images

CREATING AN IMAGE FROM SCRATCH

RUNNING MORE THAN ONE PROCESS

Logs in Containers

SECRETS IN CONTAINERS

USING CONTAINER IPS

Using The "Latest" Tag

Installing SSH

Running daemons

Containers for Fun and Profit

Containers for Fun and Profit

Multi-stage Builds

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
FROM php:7.2-fpm

COPY --from=composer:1.7 /usr/bin/composer /usr/bin/composer

Composer WIthout PHP

function composer() {
    tty=
    tty -s && tty=--tty
    docker run $tty \
        --interactive \
        --rm \
        --user $(id -u):$(id -g) \
        --volume /etc/passwd:/etc/passwd:ro \
        --volume /etc/group:/etc/group:ro \
        --volume $COMPOSER_HOME/.composer:/tmp \
        --volume $(pwd):/app \
        composer "$@"
}

Services On Demand

$ docker run --name redis -d -p 6379:6379 redis:alpine
4dfcff949ae902b619261a9287b753ee34c009bb2cc66c6ac1567aef57180cb3
$ docker exec -it redis redis-cli
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379>

Containerize All The Things

# https://github.com/jessfraz/dockerfiles

docker run -it \
	--net host \
	--cpuset-cpus 0 \
	--memory 512mb \
	-v /tmp/.X11-unix:/tmp/.X11-unix \
	-e DISPLAY=unix$DISPLAY \
	-v $HOME/Downloads:/home/chrome/Downloads \
	-v $HOME/.config/google-chrome/:/data \
	--security-opt seccomp=$HOME/chrome.json \
	--device /dev/snd \
	--device /dev/dri \
	-v /dev/shm:/dev/shm \
	--name chrome \
	jess/chrome