Docker

What are containers

A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.

What are containers

  • An image becomes a container at runtime.
  • a container will always run the same regardless of infrastructure
  • a container isolates software from its environment

Why?

Containerization is increasingly popular because containers are:

- Flexible: Even the most complex applications can be containerized.
- Lightweight: Containers leverage and share the host kernel.
- Interchangeable: You can deploy updates and upgrades on-the-fly.
- Portable: You can build locally, deploy to the cloud, and run anywhere.
- Scalable: You can increase and automatically distribute container replicas.
- Stackable: You can stack services vertically and on-the-fly.

Docker Components

  • Docker Engine: interface for running containers/creating
  • Docker Registry: where images are stored
    • Docker Hub: Cloud service for distributing containers

Installation

  • First, apt install curl
  • Use this command:
  • curl -sSL https://get.docker.com/ | sh
  • Run as normal user:
  • sudo usermod -aG docker joe
  • Reboot, see if docker commands work as normal user.

First Examples

  • docker run hello-world
  • docker - indicates to os that we are using this program
  • run - creates and runs a docker container
  • hello-world - which image to put in container

Container vs vm

A container runs natively on Linux and shares the kernel of the host machine with other containers. It runs a discrete process, taking no more memory than any other executable, making it lightweight.

By contrast, a virtual machine (VM) runs a full-blown “guest” operating system with virtual access to host resources through a hypervisor. In general, VMs provide an environment with more resources than most applications need.

Another visual

-

Docker hub

Find and run the whalesay image.

Docker

  • docker images
    • Shows images that are installed or available locally to run
  • docker --help
    • What comands are available to me
  • docker logs
    • Shows any container output

Docker Examples

  • docker run debian echo "Hello world"
    • Docker has provisioned and launched our container, executed our echo command, and then shut down the container again. If you were to try to do something similar with a traditional VM, you would be waiting several seconds, possibly minutes.
  • Containers only run as long as their main process

Container isolation

-

Docker Examples

  • docker run -h CONTAINER -i -t debian /bin/bash
    • Gives container a hostname
  • docker ps
  • docker inspect gigantic_leavitt or whatever the name is
  • docker diff gigantic_leavitt #what changes have been made
  • docker logs gigantic_leavitt #cmd history

Docker Examples

  • docker ps -a or docker container ls -a
    • Shows all containers (including stopped ones)
  • docker rm gigantic_leavitt

Dockerfile

The dockerfile provides instructions as to how to build and run an image. It can map ports to outside world. Copy stuff into container (your application code). Set environment variables, and more.

Dockerfile Example

   # Use an official Python runtime as a parent image
   FROM python:2.7-slim
   
   # Set the working directory to /app
   WORKDIR /app
   
   # Copy the current directory contents into the container at /app
   COPY . /app
   
   # Install any needed packages specified in requirements.txt
   RUN pip install --trusted-host pypi.python.org -r requirements.txt
   
   # Make port 80 available to the world outside this container
   EXPOSE 80
   
   # Define environment variable
   ENV NAME World
   
   # Run app.py when the container launches
   CMD ["python", "app.py"]

Requirements.txt and app.py.

Build the app

All I have in the directory now is:

  • app.py
  • Dockerfile
  • requirements.txt

Build the app

Build with:

  • docker build -t friendlyhello .

This creates a new image that you should be able to see with docker image ls

Run the app

  • docker run -p 4000:80 friendlyhello
  • docker run -d -p 4000:80 friendlyhello #runs detatched from terminal

Visit the ip:4000 to see your application. (Or run curl ip:4000)

Dockerfile (From)

This sets the base image for the build process.

    FROM <image>[:<tag>]

The tag is optional. If you don't specify then latest is assumed.

Example:

    FROM ubuntu:14.04

Dockerfile (Copy)

Copies from the docker host to the filesystem of the new image.

    COPY <src> ... <dst>

Multiple src files can be specified.

    COPY html /var/www/html

Dockerfile (ADD)

Similar to COPY but can handle remote URLs (like wget) and also tarred files:

    ADD <src> ... <dst>

Multiple src files can be specified

Dockerfile (ENV)

This can set an environment variable. An environment variable can be accessed anywhere in the system (by a script or app).

    ENV <key> <value> 

    ENV APACHE_LOG_DIR /var/log/apache

Dockerfile (Workdir)

Kind of like a cd. Changes current working directory to that which is specified.

Dockerfile (Volume)

The VOLUME instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers. A LOT of information about volumes can be found here.

    VOLUME <mountpoint>

Dockerfile (Expose)

The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified. To actually publish the port when running the container, use the -p or -P flag on docker run.

Dockerfile (Expose)

    EXPOSE <port> [<port>/<protocol>...]

    EXPOSE 8080

This will expose 8080 tcp port.

Dockerfile (RUN)

    RUN <command> (or)
    RUN ["executable", "param1", "param2"]

The first command is a shell command always executed at build.
The second does not automatically invoke shell /bin/sh -c.

Dockerfile (RUN)

    RUN apt-get update && \
       apt-get install -y apache2 && \
       apt-get clean

Dockerfile (CMD)

RUN executes at build time, CMD executes when the container is launched.

    CMD ["executable","param1","param2"] (exec form) (or)
    CMD command param1 param2 (shell form)

Shell form:

    FROM ubuntu
    CMD echo "This is a test." | wc -

Dockerfile (CMD)

Syntactically, you can add more than one CMD instruction in Dockerfile. However, the build system would ignore all the CMD instructions except for the last one. In other words, in the case of multiple CMD instructions, only the last CMD instruction would be effective.

Docker Networking

We also know that at container runtime, in order to actually attach to the exposed port created during the build process, we must pass in command line arguments like so:

     docker run -d -p 80:80 apachephp

Other random docker things

Force remove running container:

  • docker container rm -f <containername>

Attach to running container and execute shell in interactive mode.

  • docker exec -it apachetest bash
  • docker attach may also work
  • To leave do a cntrl+p and cntrl+q.

Host network

The container will share the same network as the host OS.

  • curl localhost:80 #shouldn't get any result
  • docker run --rm -d --network host --name my_nginx nginx
  • curl localhost:80 #should give you a default nginx page

Docker Compose

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

Sample file

    version: "3.9"  # optional since v1.27.0
    services:
      web:
        build: .
        ports:
          - "5000:5000"
        volumes:
          - .:/code
          - logvolume01:/var/log
        links:
          - redis
      redis:
        image: redis
    volumes:
      logvolume01: {}

More

  • The file should be named docker-compose.yml
  • First make sure to create your Dockerfile
  • run docker compose up

Advantages

  • Using a project name, docker compose can isolate environments from each other
  • Preserve volume data when containers are created
  • Recreate only containers that have changed
  • Can use variables to make things more dynamic

Other commands with docker-compose

  • logs -> shows container logs
  • ps -> shows running containers
  • restart
  • rm -> deletes containers
  • stop