Mastering Docker and Containerization: A Comprehensive Guide

Introduction to Containerization

In Computer Science, containerization is a vital concept involving running a process within an isolated container, separate from other system processes. This encapsulated environment includes all necessary application dependencies.

Containerization Diagram

Linux Containers (LXC)

The concept of containerization predates Docker, with the Linux Kernel API for LXC existing since 2008. LXC provides robust APIs for creating containers with their own memory, processors, and file systems.

LXC Architecture

linuxcontainers.org is the umbrella project behind LXC, LXD, and LXCFS, offering a neutral environment for Linux container technology development.

Ruby API for LXC

Ruby-LXC empowers developers to programmatically create Linux-based containers. This is instrumental in various use cases such as Platform As A Service (PAAS), micro-service architecture deployment, and CI/CD platform creation.

For more information, visit Ruby-LXC GitHub.

Installation

As of 2019, lxc is not published to RubyGems.org. You can install it in your project via GitHub.

gem "ruby-lxc", github: "lxc/ruby-lxc", require: "lxc"

Container Lifecycle Management

To build a PAAS service, understanding the lifecycle of containers is crucial. Key actions include creating, starting, stopping, and destroying containers.

require 'lxc'
c = LXC::Container.new('foo')
c.create('ubuntu') # create a container named foo with ubuntu template
c.start
# attach to a running container
c.attach do
  LXC.run_command('ifconfig eth0')
end
c.stop
c.destroy

c.create('ubuntu') - This command structures the container based on the given template, usually involving downloading and installing a Linux distribution inside the container’s root file system.

For more actions like cloning and inspection, refer to the GitHub documentation.

Hypervisor

Hypervisors are crucial software that establish an abstraction layer between the physical machine and the operating systems run on top of it. They are vital for simultaneously running different operating systems on a single machine.

There are two types of hypervisors:

  • Type 1: Directly run on the machine without the help of any host OS.
  • Type 2: Run on top of a host OS.

Type 1 and Type 2 Hypervisors

Docker and Docker Engine

Docker is a powerful containerization tool that enables the creation of containers on various operating systems like Linux, Windows, and MacOSX. While containers are natively supported by the Linux kernel, other OSes require hypervisors like VirtualBox and Hyper-V to run a Linux distribution like Boot2Docker on the host OS using docker-machine.

Installation

For Linux (Ubuntu), uninstall previous versions and install Docker:

sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

Dockerizing a Simple Ruby App

Docker provides an efficient way to containerize applications. Here’s how to Dockerize a simple Ruby app:

  1. Create a directory: mkdir simple_rack_app.
  2. Go to the directory: cd simple_rack_app.
  3. Create the necessary Ruby app files.

Dockerfile

# Dockerfile

# Use an official Ruby 2.6.3 runtime as a parent image
FROM ruby:2.6.3

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install the latest version of Bundler
RUN gem install bundler

# Install any needed packages/gems
RUN bundle install

# Make port 3000 available to the world outside this container
EXPOSE 3000

# Define environment variable
ENV

 NAME World

# Run Puma when the container launches
CMD puma -p 3000

Compilation

To compile the Docker image:

docker build --tag=simple_rack_app .

This creates an image named simple_rack_app.

Running Image

To run the image:

docker run -p 3000:3000 -t simple_rack_app

Docker Machine

Docker Machine is a tool to install docker-engine in multiple virtual hosts. It provisions virtual machines using various drivers like VirtualBox, VMware, Hyper-V, etc.

Docker Machine

Docker Storage

Ensuring data persistence in Docker is critical. Docker provides different mechanisms to achieve this, including volumes and bind mounts.

Types of Mounts in Docker

Sharing Codebase in Development

To share a codebase between the host and container in development without re-building the image:

Bind Mounts

docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

Persisting Data between Builds (e.g., Databases)

To persist data between multiple builds, creating and using volumes is a powerful approach:

# Create a new volume
docker volume create pg-database-vol

# Run an image using the same volume
docker run -t \
  -p 3000:80
  --mount source=pg-database-vol,target=/var/lib/postgresql/data \
  myrailsapp

Docker Compose

Introduction

Docker Compose is a tool that helps manage multiple containers belonging to the same application. It facilitates defining and running an application’s services and dependencies.

Docker Compose

Installation

  • Mac and Windows users get Docker Compose with Docker Desktop.
  • For Linux users, download the binaries to /usr/local/bin/:
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Usage

Docker Compose is used to orchestrate multiple services needed to run an application in different environments. It’s a three-step process:

  1. Define the app’s environment with a Dockerfile.
  2. Define the services that make up the app in docker-compose.yml.
  3. Run docker-compose up to start and run the entire app.

A sample docker-compose.yml:

version: '3'

services:
  postgres:
    image: postgres:9.6
    ports:
      - '5432:5432'
    volumes:
      - postgres:/var/lib/postgresql/data

  web:
    build: .
    command: bundle exec rails s
    env_file:
      - .env
    volumes:
      - bundle:/bundle
      - .:/app
    ports:
      - '3000:3000'
    links:
      - postgres

volumes:
  bundle:
  postgres:

Summary

Docker is a powerful tool that ensures consistent environments in both production and development. Docker Compose helps manage dependencies and services efficiently, and Docker Machine enables deployment in a micro-service fashion across multiple virtual or physical machines.

For more references: - Docker Storage - Docker Volumes - Compose Features

This comprehensive guide equips you to master Docker and containerization, improving efficiency and productivity in your development and deployment processes.