Custom Docker Images

DockerDockerBeginner
Practice Now

Introduction

Docker is a powerful tool for packaging and distributing applications as containers. At the core of this process are Docker images, which are pre-built packages containing everything needed to run an application, including the code, dependencies, and configuration. In this lab, you will learn how to create custom Docker images that enhance your applications by incorporating additional software, libraries, or configurations.

Throughout this lab, we'll be using WebIDE (VS Code) to edit files. WebIDE provides a familiar and user-friendly interface for file editing, making it easier to work with configuration files and code.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("`Docker`")) -.-> docker/ContainerOperationsGroup(["`Container Operations`"]) docker(("`Docker`")) -.-> docker/ImageOperationsGroup(["`Image Operations`"]) linux(("`Linux`")) -.-> linux/PackagesandSoftwaresGroup(["`Packages and Softwares`"]) linux(("`Linux`")) -.-> linux/FileandDirectoryManagementGroup(["`File and Directory Management`"]) docker(("`Docker`")) -.-> docker/DockerfileGroup(["`Dockerfile`"]) docker/ContainerOperationsGroup -.-> docker/exec("`Execute Command in Container`") docker/ContainerOperationsGroup -.-> docker/run("`Run a Container`") docker/ImageOperationsGroup -.-> docker/images("`List Images`") linux/PackagesandSoftwaresGroup -.-> linux/curl("`URL Data Transferring`") linux/FileandDirectoryManagementGroup -.-> linux/cd("`Directory Changing`") linux/FileandDirectoryManagementGroup -.-> linux/mkdir("`Directory Creating`") docker/DockerfileGroup -.-> docker/build("`Build Image from Dockerfile`") subgraph Lab Skills docker/exec -.-> lab-8196{{"`Custom Docker Images`"}} docker/run -.-> lab-8196{{"`Custom Docker Images`"}} docker/images -.-> lab-8196{{"`Custom Docker Images`"}} linux/curl -.-> lab-8196{{"`Custom Docker Images`"}} linux/cd -.-> lab-8196{{"`Custom Docker Images`"}} linux/mkdir -.-> lab-8196{{"`Custom Docker Images`"}} docker/build -.-> lab-8196{{"`Custom Docker Images`"}} end

Set Up the Project Environment

Let's begin by creating a project directory and navigating to it.

Throughout this lab, we'll be using WebIDE (VS Code) to edit files. WebIDE provides a familiar and user-friendly interface for file editing, making it easier to work with configuration files and code.

  1. Open a terminal in WebIDE. You can do this by clicking on "Terminal" in the top menu, then selecting "New Terminal".
  2. In the terminal, run the following commands:
mkdir -p ~/project/docker
cd ~/project/docker

This creates a new directory called docker in the ~/project folder and changes the current working directory to it.

  1. Verify that you're in the correct directory:
pwd

You should see /home/labex/project/docker as the output.

Understanding these commands:

  • mkdir -p: This command creates a directory. The -p flag allows it to create parent directories if they don't exist.
  • cd: This command changes the current directory.
  • pwd: This command prints the current working directory.

Create a Simple Docker Image

Now, let's create a simple Docker image that runs an Nginx web server.

  1. In WebIDE, navigate to the File Explorer (usually the first icon in the left sidebar).
  2. Right-click in the File Explorer pane and select "New File". Name it Dockerfile (with a capital 'D' and no file extension).
  3. Open the Dockerfile by clicking on it in the File Explorer. Add the following content:
FROM nginx
COPY index.html /usr/share/nginx/html/

This Dockerfile defines a new image based on the official Nginx image and copies a file called index.html to the default document root directory of Nginx.

Understanding the Dockerfile:

  • FROM nginx: This line specifies the base image we're building from. In this case, we're using the official Nginx image.
  • COPY index.html /usr/share/nginx/html/: This line copies our index.html file into the container's web root directory.
  1. Create a new file called index.html in the same directory. You can do this by right-clicking in the File Explorer pane again and selecting "New File".
  2. Open index.html and add the following content:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello Docker!</title>
  </head>
  <body>
    <h1>Hello Docker!</h1>
    <p>This is a custom Docker image.</p>
  </body>
</html>

This is a simple HTML page that will be served by our Nginx server.

  1. Open a terminal in WebIDE (Terminal -> New Terminal if you closed the previous one) and build the Docker image using the following command:
docker build -t my-nginx .

This command builds a new Docker image with the tag my-nginx.

Understanding the command:

  • docker build: This is the command to build a Docker image.
  • -t my-nginx: The -t flag tags our image with the name my-nginx.
  • .: This specifies the build context (the directory containing the Dockerfile) as the current directory.
  1. Once the build is complete, verify that the image was created successfully:
docker images

You should see the my-nginx image listed in the output.

Run and Test the Custom Image

Let's run a container based on our new image and test it.

  1. In the WebIDE terminal, start a container using the following command:
docker run -d -p 8080:80 --name my-nginx-container my-nginx

Understanding this command:

  • docker run: This command creates and starts a new container.
  • -d: This flag runs the container in detached mode (in the background).
  • -p 8080:80: This maps port 8080 on your host to port 80 in the container.
  • --name my-nginx-container: This assigns a name to our container.
  • my-nginx: This is the name of the image we're using to create the container.
  1. Verify that the container is running:
docker ps

You should see my-nginx-container listed in the output. This command shows all running containers.

  1. To view the contents of the web page, use the curl command:
curl http://localhost:8080

You should see the HTML content of the index.html file displayed in the terminal.

If you're curious about what curl does, it's a tool to transfer data from or to a server. In this case, we're using it to fetch the content from our web server.

You can also navigate to the top of the LabEx VM, and click + to create a new web sever, and then enter the port 8080 to view the content.

alt text

Add Custom Software to the Image

Now, let's modify our Docker image to include additional software. We'll add the curl utility as an example.

  1. In WebIDE, open the Dockerfile. You can do this by clicking on Dockerfile in the File Explorer pane.
  2. Modify the content of the Dockerfile to:
FROM nginx
RUN apt-get update && apt-get install -y curl
COPY index.html /usr/share/nginx/html/

This Dockerfile adds a new RUN instruction that updates the package index and installs the curl utility using the apt-get package manager.

Understanding the new line:

  • RUN apt-get update && apt-get install -y curl: This line updates the package list (apt-get update) and then installs curl (apt-get install -y curl). The -y flag automatically answers "yes" to any prompts during installation.
  1. Save the file in WebIDE by pressing Ctrl+S (or Cmd+S on Mac).
  2. In the WebIDE terminal, rebuild the Docker image with a new tag:
docker build -t my-nginx-curl .

This command builds a new Docker image with the tag my-nginx-curl that includes the curl utility.

  1. Verify that the new image was created:
docker images

You should see the my-nginx-curl image listed in the output.

Test the Custom Image with Curl

Let's run a container based on our new image and test the curl utility.

  1. In the WebIDE terminal, start a new container using the following command:
docker run -d --name curl-container my-nginx-curl

This command starts a new container based on the my-nginx-curl image and names it curl-container.

  1. Execute a bash shell in the running container:
docker exec -it curl-container bash

This command opens an interactive bash shell inside the running container.

Understanding this command:

  • docker exec: This runs a command in a running container.
  • -it: These flags allocate a pseudo-TTY and keep STDIN open, allowing you to interact with the shell.
  • curl-container: This is the name of our container.
  • bash: This is the command we're running in the container (opening a bash shell).
  1. You should now see a new prompt, indicating you're inside the container. Inside the container, test the curl utility:
curl http://localhost

You should see the HTML content of the index.html file displayed in the terminal.

  1. Exit the container's bash shell:
exit

This command returns you to your host system's shell.

Use Environment Variables in the Image

In this step, we'll modify our Docker image to use environment variables for customization.

  1. In WebIDE, open the Dockerfile again.

  2. Modify the content of the Dockerfile to:

FROM nginx
ENV NGINX_PORT 9000
RUN sed -i "s/listen\s*80;/listen $NGINX_PORT;/g" /etc/nginx/conf.d/default.conf
COPY index.html /usr/share/nginx/html/

This Dockerfile adds an ENV instruction that sets the NGINX_PORT variable to 9000. It also includes a RUN instruction that modifies the Nginx configuration to use this port.

Understanding the new lines:

  • ENV NGINX_PORT 9000: This sets an environment variable NGINX_PORT with the value 9000.
  • RUN sed -i "s/listen\s*80;/listen $NGINX_PORT;/g" /etc/nginx/conf.d/default.conf: This uses sed to replace the default port (80) with our environment variable in the Nginx configuration file.
  1. Save the file in WebIDE.

  2. In the WebIDE terminal, rebuild the Docker image with a new tag:

docker build -t my-nginx-env .
  1. Run a container based on the new image:
docker run -d -p 9000:9000 -e NGINX_PORT=9000 --name env-container my-nginx-env

This command starts a new container based on the my-nginx-env image, maps port 9000 on the host to port 9000 in the container, and sets the value of the NGINX_PORT variable to 9000.

Understanding the new parts of this command:

  • -e NGINX_PORT=9000: This sets the environment variable NGINX_PORT to 9000 for this specific container run.
  1. Verify that the web server is running on the specified port:
curl http://localhost:9000

You should see the HTML content of the index.html file displayed in the terminal.

Use ENTRYPOINT in Dockerfile

In this step, we'll learn how to use the ENTRYPOINT instruction in a Dockerfile and use a different port (9100).

  1. In WebIDE, open the Dockerfile again.

  2. Modify the content of the Dockerfile to:

FROM nginx
ENV NGINX_PORT 9100
RUN sed -i "s/listen\s*80;/listen $NGINX_PORT;/g" /etc/nginx/conf.d/default.conf
COPY index.html /usr/share/nginx/html/
COPY start.sh /start.sh
RUN chmod +x /start.sh
ENTRYPOINT ["/start.sh"]

This Dockerfile sets the NGINX_PORT to 9100 and adds an ENTRYPOINT instruction, which specifies the command to run when the container starts.

  1. Create a new file named start.sh in the same directory with the following content:
#!/bin/bash
echo "Starting Nginx on port $NGINX_PORT"
nginx -g 'daemon off;'

This script prints a message showing which port Nginx will run on before starting Nginx.

  1. Save both files in WebIDE.

  2. In the WebIDE terminal, rebuild the Docker image with a new tag:

docker build -t my-nginx-entrypoint .
  1. Run a container based on the new image:
docker run -d -p 9100:9100 -e NGINX_PORT=9100 --name entrypoint-container my-nginx-entrypoint
  1. Check the container logs to see the startup message:
docker logs entrypoint-container

You should see the message "Starting Nginx on port 9100" in the output.

  1. Verify that the web server is running correctly on the new port:
curl http://localhost:9100

You should see the HTML content of the index.html file displayed in the terminal.

Summary

In this lab, you have learned how to create custom Docker images that add value to your applications. You started by creating a simple image with a web server, then progressed to adding custom software and using environment variables for configuration. Throughout the lab, you've used WebIDE (VS Code) to edit files, making the process more intuitive and user-friendly.

Here's a recap of what you've accomplished:

  1. Set up a project environment and learned basic terminal commands.
  2. Created a simple Docker image with Nginx and a custom HTML page.
  3. Built and ran Docker containers, learning about port mapping and container naming.
  4. Modified a Docker image to include additional software (curl).
  5. Used Docker exec to run commands inside a container.
  6. Incorporated environment variables into your Docker image for easier configuration.

Other Docker Tutorials you may like