Docker introduction


Docker Image and Container concepts

An image is typically a layered operating system file, such as Alpine Linux, which is a commonly used OS used with Docker. Images are downloaded.

A container is a build of the image with a defined configuration. Containers are run.
Docker Compose allows multiple containers to run.


Dockerfile defines image to build, operating system, configuration. Note capital D.

docker-compose.yml can orchestrate containers

Dockertoolbox is legacy

Getting started

Install Docker

Preferably on a Linux based system.  Ive had success on Debian, Windows WSL2 subsystem (Ubuntu), and Mac OS (Intel CPU).  Running natively on Windows I can't recommend.  Ive read that there is now support for M1 Macs too.

Define the image to build

Dockerfile example, pulls in another Dockerfile from as a starting point, copies the source code from local into the VM, and opens port 80.

# Use existing image from as starting point
# OS and stack
FROM php7.0-apache

# Copy local source code into the virtual machine
COPY src/ /var/www/html

# Expose port(s)

Build the image

This should be run in the same location as the Dockerfile

docker build -t my-image .

-t tags the image with a human readable name

List all Docker images

This shows all the images that Docker has built, from these images containers can be built

Docker images

Build and run a container from the image

docker run -p 80:80 my-image

Note in the above the source code is statically copied from local into the virtual machine.

Build and run a container from the image
and mount the source code into the virtual machine

docker run -p 80:80 -v /full/local/path/to/sourcecode:/var/www/html my-image

Build and run a public image from

docker run -t -i centos:centos6 /bin/bash

Connect to a running container

docker attach [machineID]

Docker Compose

Docker Compose is a tool to help define and share multi-container applications. We can create a YAML file to define the services and with a single command, can spin everything up or tear it all down.

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.

  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.

  3. Run docker-compose up and Compose starts and runs your entire app.

docker-compose.yml looks like this:

version: '2.0'
    build: .
    - "5000:5000"
    - .:/code
    - logvolume01:/var/log
    - redis
    image: redis
  logvolume01: {}

Standard LAMP (debian, mariadb) Example


version: '3.7'

        image: php:7.3-apache
            - 80:80
            - "/Users/ross/Sites/observium/www/:/var/www/html"

        image: mariadb:10.5.2
            - mariadb-volume:/var/lib/mysql
            TZ: "Europe/London"
            MYSQL_ROOT_PASSWORD: "root"
            MYSQL_USER: 'test'
            MYSQL_PASSWORD: 'test'
            MYSQL_DATABASE: 'test'

        image: phpmyadmin/phpmyadmin
            - 'mariadb:db'
            - 8081:80



Standard LAMP (ubuntu, mariadb) Example

Create a www folder in /Users/ross/Sites/observium/ with an index.html file

Build and run the container:

docker-compose up -d --build

This creates a standard LAMP instance with PHPMyAdmin that is running in the background.

To SSH into the running container:

  • Use docker ps to get the name of the existing container

  • Use the command docker attach or docker exec -it <container name> /bin/bash to get a bash or shell (replace /bin/bash with sh) in the container

  • Exit container: exit or CTRL + P then Q

  • Generically, use docker exec -it <container name> <command> to execute whatever command you specify in the container.

Docker Networking

Networking allows you to run docker on its own self contained network without worry that it will interfere with any other docker hosts on your system, should you have a host name clash for example.

By default, Docker uses bridge network mode. This is not recommended for production.

Hosts can ping each other by IP on the default bridge network, but not ping by hostname.

On custom bridge networks ping by ip and hostname will work because they use Automatic Network Discovery service.

Its possible for a host to be on more than one bridge network if needed.

Setting up a container to use a custom bridge network:

$ docker run -d --name alpine1 --network alpine-net alpine ash

(Note ash is Alpines version of bash)

You can also define the network in docker-compose.yml file.  

Docker bind mount vs volumes

A bind mount, is best for local development as is mounts a directory from the host into the container using a mount point.

A volume is best used in production as it ‘clones’ the contents of the host directory to the container. Changes to the host directory contents are synced in realtime with the container folder.


Popular posts from this blog

Rant: Don't name your mobile app with a pronoun prefix

Web 3.0: Component driven responsive design

Why you should use rem instead of px in webdesign