Skip to content

Instantly share code, notes, and snippets.

@spilth
Created August 10, 2021 19:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spilth/35aac32ec25496415a634375ed5291ed to your computer and use it in GitHub Desktop.
Save spilth/35aac32ec25496415a634375ed5291ed to your computer and use it in GitHub Desktop.

class: center, middle

Running Application Services for Local Development using Docker & Docker Compose

⚡️⚡️⚡️

Brian Kelly


The Goal

Get developers up and running fast with all the services an application needs to run so they can develop and test locally against the same services that are running in production.


class: center, middle

The Basics


What is Docker?

Docker is a software platform that simplifies the process of building, running, managing and distributing applications.


Installing Docker

Install it using Homebrew:

$ brew install docker           # Install the command-line tools
$ brew install --cask docker    # Install the desktop application
$ open /Applications/Docker.app # Start up the desktop application

Then wait for the desktop app to finish starting up.


Hello World?

To quickly check that everything is cool, use docker run hello-world:

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete 
Digest: sha256:df5f5184104426b65967e016ff2ac0bfcd44ad7899ca3bbcf8e44e4461491a9e
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

What just happened?

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

What's an Image? What's a Container?

  • A Docker Image contains application code, libraries, tools, dependencies and other files needed to make an application run.
  • A Container is a runnable instance of an Image.

Where do I find Images?

Go to https://hub.docker.com/ and search!


How do I download an Image?

Use docker pull to download an Image.

$ docker pull IMAGE_NAME

Additionally the run and exec commands will download an image if you don't already have it.


What Images are on my machine?

Use docker image ls to see what Images are on your machine:

$ docker image ls
REPOSITORY     TAG           IMAGE ID       CREATED        SIZE
rabbitmq       management    737d67e8db84   6 days ago     253MB
ubuntu         latest        1318b700e415   13 days ago    72.8MB
redis          5             38912efffc60   2 weeks ago    98.4MB
postgres       12            0f698a6badfa   2 weeks ago    314MB
hello-world    latest        d1165f221234   5 months ago   13.3kB

What is a Tag?

  • It's essentially a version number.
  • The tag latest is generaly used to represent the most recent version of an image.
  • Tags can also be used to differentiate different flavors of an image.

How do I start a Containers?

Use the docker run command.


class: center, middle

Some Examples


Example: IRB for the latest Ruby

Run the latest ruby image with an interactive terminal.

$ docker run —interactive —tty ruby
irb(main):001:0> RUBY_VERSION
=> "3.0.2"
irb(main):002:0> exit

Example: IRB for Ruby 2.7.2

Use -it in place of —interactive —tty

$ docker run -it ruby:2.7.2         
irb(main):001:0> RUBY_VERSION
=> "2.7.2"
irb(main):002:0> exit

Example: RabbitMQ 3.8.20 with the Management Plugin

Run RabbitMQ in the background and make the web interface accessible on port 15672.

$ docker run \
  --detach \
  --publish 15672:15672 \
  --name rabbit \ 
  rabbitmq:3.8.20-management
$ open http://localhost:15672

Example: Shelling into RabbitMQ Container

Using docker exec to run a shell on a running Container:

$ docker exec -it rabbit /bin/sh 
# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
+--------------------+---------+
# exit
$ docker stop rabbit

Example: PostgreSQL Server

Run Postgres in the background with a specific username/password, make it accessible to the host machine on port 5432, persist database data locally and give the container a name:

$ docker run \ 
  --detach \
  --env POSTGRES_USER=$USER \ 
  --env POSTGRES_PASSWORD=password \ 
  --publish 5432:5432 \ 
  --volume ~/docker-data/postgres:/var/lib/postgresql/data \ 
  --name rails_pg \ 
  postgres

PostgreSQL: Again with Shorter Flags

$ docker run \
  -d \
  -e POSTGRES_USER=$USER \
  -e POSTGRES_PASSWORD=password \
  -p 5432:5432 \
  -v ~/docker-data/postgres:/var/lib/postgresql/data \
  --name rails_pg \
  postgres

class: center, middle

There's got to be a better way!

🤷🏻‍♀️


Docker Compose

Compose is a tool for defining and running multi-container Docker applications.


PostgreSQL: Docker Compose

Create a file named docker-compose.yml:

version: "3.9"

services:
  postgres:
    image: "postgres:12"
    environment:
      - POSTGRES_USER=username
      - POSTGRES_PASSWORD=password
    ports:
      - "5432:5432"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data

Bringing Services Up

$ docker-compose up --detach

Taking Services Down

$ docker-compose down

Example: Multiple Services

version: "3.9"

services:
  postgres:
    image: "postgres:12"
    environment:
      - POSTGRES_USER=username
      - POSTGRES_PASSWORD=password
    ports:
      - "5432:5432"
		volumes:
      - ./data/postgres:/var/lib/postgresql/data

  rabbitmq:
    image: "rabbitmq:management"
    ports:
      - "5672:5672"
      - "15672:15672"

  redis:
    image: "redis:5"
    ports:
      - "6379:6379"

class: center, middle

Maintenance


Docker Disk Usage

$ docker system df  
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          18        17        7.793GB   1.757GB (22%)
Containers      18        5         140.1MB   134.2MB (95%)
Local Volumes   19        17        1.634GB   439.6MB (26%)
Build Cache     0         0         0B        0B

Cleaning Up Images

$ docker image ls           # List Images
$ docker image ls --all     # List Intermediate Images
$ docker image rm IMAGE_ID  # Remove Image by ID
$ docker image prune        # Remove "dangling" Images
$ docker image prune --all  # Remove all unused Images

Cleaning Up Containers

$ docker container ls            # List Only Running Containers
$ docker container ls --all      # List All Containers
$ docker container rm ID_OR_NAME # Remove Container by Container ID or Name

The Nuclear Option

$ docker system prune
$ docker system prune --all # Remove all unused images not just dangling ones

class: center, middle

How do I create my own Images?

😅 Thank you for coming! 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment