Complete Intro to Containers (feat. Docker)
Table of Contents
IntroductionBrian Holt gives an overview of the course, explains why containers are a relevant topic for any software engineer, discusses what needs to be installed to follow along, and shares where to file issues with the course.
ContainersBrian gives a brief history of why containers are useful tools that host controlled and isolated environments, thanks to a frozen file system. The latter allowed engineers to have access to ready to use containers without having to recreate all the dependencies and file system on a local machine.
chrootBrian explains that chroot is a Linux kernel feature that allows the containment of processes, restricts a process to a certain file tree, and uses chroot to add bash commands to the bash directory. A chroot operation is necessary to understand how containers are layered to limit or deny access outside of a designated directory tree.
chroot ExerciseStudents are instructed to use the chroot process to make the bash command cat function within the bash directory.
chroot SolutionBrian live codes the solution to the chroot exercise.
NamespacesBrian explains that namespaces are useful to hide processes, networks, and other configurations from other environments, and demonstrates how to configure namespaces and use a command nammed unshare to seperate environments. The parent process has access to the child process, but the child cannot access the parent.
cgroupsBrian explains that cgroups were invented by Google to limit what resources a process can access to avoid entire servers shutting down, and demonstrates how to manually use cgroups to restrict processes.
Getting Set Up with DockerBrian explains that Docker is a command line tool that makes building and managing containers easier, and that has environments built in various languages. Docker allows engineers to build a container in less time and fewer lines of code because it manages chroot, namespaces, and cgroups for the engineer.
Docker Images without DockerBrian demonstrates how to download a container, unpack it, and run it on its own without involving Docker.
Docker Images with DockerBrian demonstrates how to use a one line command to build a container instead of using the longer process live coded in the previous section, explains that images take memory space, and shows how to prune them.
Node.js on DockerBrian demonstrates how to create a Node.js container that uses Debian instead of Ubuntu after mentioning that there is a wide variety of containers using different libraries and laguages. Debian is used instead of Ubuntu because Node images were created in Debian.
TagsBrian explains that it is important to tie tags to specific versions when creating environments to avoid dependency issues that would break the code, and shares the rules of thumb when picking tags to build a container.
Docker CLIBrian shares a few commands in the Docker CLI that give the container's history, pause the container, erase the container, or run a container with, and how to prune stopped containers.
Dockerfiles PreambleBrian demonstrates how to create a Dockerfile, adds a series of instructions in the Dockerfile that will give information about how the container should run, and how to tag a container and run it.
Build a Node.js AppBrian demonstrates how to build a Node.js application within a container, and writes a Dockerfile for a Node app.
Run a Node.js AppBrian explains how to add publishing ports, how to stop a running container, and how to set up a secure user within the container that is different from the root user.
Add Dependencies to a Node.js AppBrian demonstrates how to install dependencies into the new Node.js app, making the app more complex, and adds a Dockerfile to the app.
EXPOSEBrian explains what port mapping is using EXPOSE, a Dockerfile command that explicitly instructs users to check a specific port, and demonstrates that it is more convinient to add this information to the markdown of a specific app, instead of Dockerfile.
LayersBrian demonstrates that a Docker container is composed of layers, and explains how to add a COPY command to the Docker file that will cache the layers of the built container and skip right to the new added layers when rebuilding a container.
Docker IgnoreBrian demonstrates how to add a dockerignore file, and explains that the files mentioned within the dockerignore document are files that should not be copied from the host operating system into the container, but that are still necessary within a project.
Making Tiny Containers
Alpine LinuxBrian demonstrates how to use Alpine Linux, and explains that Alpine Linux is the smallest barebone distribution of Linux, it is therefore more secure because there are less files and less vulnerabilities.
Alpine Node.js ContainerBrian demonstrates how to build a container from scratch using Alpine Linux, and explains that the goal is to build a container that is smaller than the standard Alpine container, and simpler. A Node.js app is added to the container.
Multi-Stage BuildsBrian demonstrates how to create a multistage build, and explains that it is more secure to build smaller Alpine Node.js containers and only gives the tools necessary to build the container. Multi-stage builds are useful to optimize Dockerfiles by keeping them easy to read and maintain.
Static Assets Project ExerciseStudents are instructed to create a multi stage build, copy a React project, build it, and transfer it to an NGINX container.
Static Assets Project SolutionBrian live codes the solution to the static assets project exercise.
Features in Docker
Bind MountsBrian explains that bind mounts ship files from the host computer into the container. Bind mounts allow access to preexisting development environments, which fast forwards the work of engineers.
VolumesBrian describes volume mounts as tools that maintain state between runs by saving the results from the previous run.
Containers & Dev EnvironmentBrian builds a Hugo static site within a container, and explains that containers can also be development environments, which makes them shareable and recreatable.
Dev Containers with Visual Studio CodeBrian demonstrates how to set up dev containers using VS Code and explains that one can open a remote container using VS Code.
Networks & Docker: MongoDB ContainerBrian introduces networking in Docker by connecting multiple containers to each other, and builds a container using MongoDB.
Networks & Docker: Client Side ContainerBrian demonstrates how to connect two different containers by live coding a Node.js application in a container and connecting it to the container created in the previous section.
Multi Container Projects
Docker ComposeBrian explains how to build a docker-compose.yml file which sets up multiple containers without needing to build a development environment for each container.
Docker Compose & nodemonBrian adds nodemon, a file watcher that restarts Node every time it notices a file change, making development more seemless, and demonstrates how to start multiple containers at the same time.
Kubernetes FundamentalsBrian explains that Kubernetes is used for production workload and is useful when a lot of containers and different services are involved with complex relationships with each other, and goes over the fundamental terminology and concepts of Kubernetes.
Kubernetes & kubectlBrian demonstates how to interact with Kubernetes, explains that using Kubernetes is a complex task that generally happens during production, and demonstrates how to use kubectl. Kubectl is a command line interface that manages a Kubernetes cluster.
KomposeBrian introduces the Kompose tool, and demonstrates how to convert docker-compose.yml into a Kubernetes file. Kompose is a conversion tool that transforms Docker Compose to container orchestrators such as Kubernetes.
Multiple Containers with KomposeBrian demonstrates how to run multiple containers using Kompose, how to delete all of the newly created containers, and how to convert all files to Kubernetes files.
BuildahBrian explores alternatives to Docker, starting with Buildah. Buildah allows users to build containers using bash scripts or to build an OCI container with a Dockerfile via Buildah.
Buildah & DockerBrian demonstrates how to build a Buildah container within a Docker container.
PodmanBrian introduces Podman which allows users to run OCI or Docker container, and runs the previously built container with Podman.
Wrapping UpBrian wraps up the course by sharing additional topics that students can learn about, additional resources about non Docker containers, and information about orchestration systems such as Docker Swarm, Apache Mesos, and Hashicorp Nomad. Questions are fielded from the audience about container monitoring, using Gatsby with containers, and the difference between CMD and run.