Dockerfiles

Cards (23)

  • Dockerfiles play an essential role in Docker. Dockerfiles is a formatted text file which essentially serves as an instruction manual for what containers should do and ultimately assembles a Docker image.
    • You use Dockerfiles to contain the commands the container should execute when it is built. To get started with Dockerfiles, we need to know some basic syntax and instructions. Dockerfiles are formatted in the following way:
    • INSTRUCTION argument
  • FROM
    • This instruction sets a build stage for the container as well as setting the base image (operating system). All Dockerfiles must start with this.
    • Example: FROM ubuntu
  • RUN
    • This instruction will execute commands in the container within a new layer.
    • Example: RUN whoami
  • COPY
    • This instruction copies files from the local system to the working directory in the container (the syntax is similar to the cp command).
    • COPY /home/cmnatic/myfolder/app/
  • WORKDIR
    • This instruction sets the working directory of the container. (similar to using cd on Linux).
    • Example: WORKDIR /(sets to the root of the filesystem in the container)
  • CMD
    • This instruction determines what command is run when the container starts (you would use this to start a service or application).
    • Example: CMD /bin/sh -c script.sh
  • EXPOSE
    • This instruction is used to tell the person who runs the container what port they should publish when running the container.
    • Example: EXPOSE 80
    (tells the person running the container to publish to port 80 i.e. docker run -p 80:80)
    1. Use the “Ubuntu” (version 22.04) operating system as the base.
    2. Set the working directory to be the root of the container.
    3. Create the text file “helloworld.txt”.
    • Remember, the commands that you can run via the RUN instruction will depend on the operating system you use in the FROM instruction. (In this example, I have chosen Ubuntu. It’s important to remember that the operating systems used in containers are usually very minimal. I.e., don’t expect a command to be there from the start (even commands like curlping, etc., may need to be installed.)
  • Building Your First Container
    • Once we have a Dockerfile, we can create an image using the docker build command. This command requires a few pieces of information:
    1. Whether or not you want to name the image yourself (we will use the -t (tag) argument).
    2. The name that you are going to give the image.
    3. The location of the Dockerfile you wish to build with.
  • Let’s say we want to build an image - let’s fill in the two required pieces of information listed above:
    1. We are going to name it ourselves, so we are going to use the -t argument.
    2. We want to name the image.
    3. The Dockerfile is located in our current working directory (.)
    Let’s say we want to build an image - let’s fill in the two required pieces of information listed above:
    1. We are going to name it ourselves, so we are going to use the -t argument.
    2. We want to name the image.
    3. The Dockerfile is located in our current working directory (.).
  • Let’s level up our Dockerfile. So far, our container will only create a file - that’s not very useful! In the following Dockerfile, I am going to:
    1. Use Ubuntu 22.04 as the base operating system for the container.
    2. Install the “apache2” web server.
    3. Add some networking. As this is a web server, we will need to be able to connect to the container over the network somehow. I will achieve this by using the EXPOSE instruction and telling the container to expose port 80.
  • Levelling up Our Dockerfile
    Let’s level up our Dockerfile. So far, our container will only create a file - that’s not very useful! In the following Dockerfile, I am going to: 4. Tell the container to start the “apache2” service at startup. Containers do not have service managers like systemd (this is by design - it is bad practice to run multiple applications in the same container. For example, this container is for the apache2 web server - and the apache2 web server only).
    • docker run -d --name webserver -p 80:80  webserver
  • Optimising Our Dockerfile
    • For example, you can reduce the size of a docker image (and reduce build time!) using a few ways:
    1. Only installing the essential packages. What’s nice about containers is that they’re practically empty from the get-go - we have complete freedom to decide what we want.
    2. Removing cached files (such as APT cache or documentation installed with tools). The code within a container will only be executed once (on build!), so we don’t need to store anything for later use.
  • Optimising Our Dockerfile
    • For example, you can reduce the size of a docker image (and reduce build time!) using a few ways:
    1. Using minimal base operating systems in our FROM instruction. Even though operating systems for containers such as Ubuntu are already pretty slim, consider using an even more stripped-down version (i.e. ubuntu:22.04-minimal). Or, for example, using Alpine (which can be as small as 5.59MB!).
    2. Minimising the number of layers.
  • Optimizing our Dockerfiles:
    • Each instruction (I.E. FROM, RUN, etc.) is run in its own layer. Layers increase build time! The objective is to have as few layers as possible.
    • For example, try chaining commands from RUN together like so:
    Before:
    FROM ubuntu:latest RUN apt-get update -y RUN apt-get upgrade -y
    • RUN apt-get install apache2 -y RUN apt-get install net-tools -y
    After:
    FROM ubuntu:latest
    • RUN apt-get update -y && apt-get upgrade -y && apt-get install apache2 -y && apt-get install net-tools
  • Note here how there are now only two build steps (this will be two layers, making the build much quicker). This is just a tiny example of a Dockerfile, so the build time will not be so drastic, but in much larger Dockerfiles - reducing the number of layers will have a fantastic performance increase during the build.
  • Specify Base Image:
    • Choose a base image from Docker Hub.
  • Set the Working Directory:
    • Define the working directory inside the container.
  • Copy Files into the Image:
    • Copy files from the host to the image.
  • Install Dependencies:
    • Use package managers to install required software.
  • Expose Ports:
    • Document which ports the application will use.
  • Define Environment Variables:
    • Set environment variables for the application.