Docker

Chandan’s Docker Notes here

Dockerfile CLI interaction

Dockerfile Blueprint of image - example of infrastructure as code

Rails Docker

Every image has to start from something: another, preexisting image. For that reason, every Dockerfile begins with a FROM instruction, which specifies the image to use as its starting point. Typically, we’ll look for a starting image that’s close to what we need but more general. That way we can extend and customize it to our needs.

Docker compose

docker run gives us an ability to run a single container, however, that’s not sufficient to run our application. We at least want a DB to run. That’s where docker compose comes into picture.

Compose handles the grunt work of ensuring the right containers are run when and how you need. It also manages creating and destroying the resources needed for the app. For example, it creates a separate, private network for your application, giving you a predictable, isolated environment.

docker-compose.yml

Notable Docker images/libraries

Check out docker library repositories here

Docker Entrypoint

Example: docker-entrypoint.sh

#!/bin/bash
set -e

if [ "$1" = 'redis-server' ]; then
    chown -R redis .
    exec gosu redis "$@"
fi

exec "$@"
ENTRYPOINT is one of the many instructions you can write in a dockerfile. 
The ENTRYPOINT instruction is used to configure the executables that will always
 run after the container is initiated. For example, you can mention a script to 
 run as soon as the container is started. Note that the ENTRYPOINT commands cannot 
 be overridden or ignored, even when you run the container with command line arguments.
using exec will replace the parent process, rather than have two processes running.

This is important in Docker for signals to be proxied correctly. For example, if Redis was started without exec, it will not receive a SIGTERM upon docker stop and will not get a chance to shutdown cleanly. In some cases, this can lead to data loss or zombie processes.

If you do start child processes (i.e. don't use exec), the parent process becomes responsible for handling and forwarding signals as appropriate. This is one of the reasons it's best to use supervisord or similar when running multiple processes in a container, as it will forward signals appropriately.
  • Docker Entrypoint vs CMD
    Use ENTRYPOINT instructions when creating an executable Docker image with commands 
    that must always be executed. • Use CMD instructions for an additional set of arguments
     that will serve as default instructions in case there is an explicit command line 
     argument provided when the container runs.
    

Container Orchestration

Container Orchestration is a process to configure, run, and update the multiple containers that make up an application in concert.

  • Orchestrators expose secret management as an application-level feature.
Docker Swarm AND kubernetes

Swarm has the concept of a stack, which envisions the application as a group of underlying services. Kubernetes, on the other hand, breaks this down further into a Deployment, made up of ReplicaSets, which in turn are made up of Pods.

Docker Swarm

Pro -

  • Swarm manager nodes can run workload containers in addition to their cluster management Con -
  • No Autoscaling
Kubernetes

Pro -

  • Autoscaling Con -
  • Kubernetes Manager can just do cluster management
  • More verbose configuration and complex

Environment specific

In Dockerfile:

FROM ruby:3.2.2

ENV ENVIRONMENT=development

Staging:

  • To build/run a service with ENVIRONMENT staging and tag : ```shell $> docker build --build-arg ENVIRONMENT=staging -t rails-api:staging . $> docker run -e ENVIRONMENT=staging rails-api:staging
This `ENVIRONMENT` will be substituted in Dockerfile while building the image.

Environment variables can be overridden while `docker-compose` as well.
```shell
$> docker-compose -f docker-compose.yml up -e ENVIRONMENT=development

envsubst is linux too to substitute environment variables in a file.

You can publish your docker image to any Docker Container Registry.

in a Docker Compose file, you can specify both the image and build options for a service. Here’s an example of how you can specify both in the docker-compose.yml file for the rails-api service:

services:
  rails-api:
    image: orendaa-rails-api:latest
    build:
      context: ./rails-api
      dockerfile: Dockerfile

In the above example, the image option specifies the name and tag of the pre-built image to use for the service. The build option specifies the build context and Dockerfile location to build the image if it doesn’t exist.

When you run docker-compose up or docker-compose build, Docker Compose will first check if the specified image exists. If it does, it will use the existing image. If not, it will build the image using the specified build context and Dockerfile.

By specifying both image and build, you have the flexibility to use a pre-built image if available, or build the image from the specified build context if the image doesn’t exist.

Check docker-compose configuration

$> docker-compose config

This is a sapling 🌱 in my digital garden 🏡.

Notes mentioning this note


Here are all the notes in this garden, along with their links, visualized as a graph.