Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

A practical introduction to Docker containers

 

May 15, 2014
Scott McCarty (fatherlinux), Joe Brockmeier
Related products:
Red Hat OpenShift Container Platform

Share:

    Background

    Why

    Docker has quite an amount of buzz around it today because it makes so many things easy that were difficult with virtual machines.

    Docker containers makes it easy for Developers, Systems Administrators, Architects, Consultants and others to quickly test a piece of software in a container; much quicker than a virtual machine, and using less resources. The average command in Docker takes under a second to complete.

    [root@keith]# time docker run fedora cat /etc/redhat-release
    Fedora release 20 (Heisenbug)
    real 0m0.715s
    user 0m0.004s
    sys 0m0.004s

     

    What

    Simple Use Cases

    • I need to see the man page from a specific version of RHEL, CentOS or Fedora
    • I need to quickly verify the command line options of a program
    • I need to test the functionality of a specific version of software
    • I need a scratch pad that is NOT my system
    • I need a single daemon running, and I don't care what distribution of Linux it runs on (see registry below)

     

    Complex Use Cases

    Docker containers run a single process when started, but complex installations of software which require multiple daemons running simultaneously (RHEV-M, Satellite, etc) can be done. However, they require more engineering work using either Bash scripting or running SystemD in the container.

    Production vs. Development

    The Docker tooling reached 1.0 in June, 2014 and with some precautions, can be used in production. There is a lot to think about with a production deployment, and I suggest readying the Architecting Containers series if you are seriously considering a production deployment.

    CentOS and Red Hat Enterprise Linux

    This tutorial will focus on integration with Red Hat technologies including CentOS and Red Hat Enterprise Linux. The Docker tooling (daemon and client) is available in Red Hat Enterprise Linux, CentOS, and Fedora. Also, base Docker images are available for Red Hat Enterprise Linux (6 and 7), CentOS and Fedora.

    Architecture

    One of the key advantages of using Docker is it's centralized image management server, called a Registry Server. The Docker project maintains a public registry server which hosts images they maintain, as well as images created by the community. This registry service is free to use, as long as the images are public.

    As one builds images, they are made up of layers. These layers are shared together in, what is called a repository. Users on the registry can share multiple repositories.

    Docker has official CentOS and Fedora repositories which they support:

    • centos
    • fedora

     

    This tutorial will use public CentOS Fedora repositories, but you may also run through this tutorial using Red Hat Enterprise Linux:

    • rhel

     

    OS Virtualization vs. Application Virtualization

    Why separate RPMs for each major version of Red Hat Enterprise Linux or CentOS into different YUM repositories? This was a conscious decision because we are working with a full enterprise Linux distribution versus a single application. Historically, it has been best practice to install a fresh copy when upgrading major versions of Red Hat Enterprise Linux or CentOS. While it is possible to upgrade in place and share multiple versions in a single repository, this is not the preferred method with an enterprise operating system.

    However, when virtualizing individual applications, it may be very appropriate to upgrade in place and share all versions within a single repository (See section: Set Up a Registry Server). Each version will be tagged in place and it's easy to upgrade or downgrade atomically.

    Registry Servers

    After reading this tutorial, you may be excited to set up your own registry server. This is easy to do, but has some caveats, so think through whether it is worth just using a hosted registry server. If you want to deploy an onsite registry server, there are several options:

    • Integrated OpenShiftRegistry Server: The OpenShift integrated registry provides authentication and tight integration with OpenShift, but can also be used as a stand alone registry server.
    • Atomic Registry: This is the same registry server provided in OpenShift
    • Red Hat Satellite with Docker Plugin: Provides Docker compatible repository management. Has the ability to authenticate who can save image layers, and do version control.
    • docker-distribution.x86_64: Docker toolset to pack, ship, store, and deliver content. An RPM for this package is included in RHEL7.
    • docker-registry.x86_64: Registry server for Docker. An RPM for this package is included in RHEL7.

    Basic Operations

    Now we will run through some basic operations to get you up and running.

    Install Docker

    In CentOS 7, this requires the user space tools and daemon to be installed from an RPM. On Red Hat Enterprise Linux, this RPM is contained in the rhel-7-server-extras-rpms/x86_64 channel.

    yum install docker
    systemctl enable docker.service
    systemctl start docker.service
    

     

    Test Docker

    This will automatically pull the latest CentOS 4 image from the remote repository and cache it locally.

    docker run -it centos cat /etc/redhat-release

     

    Pull an Image

    This will pull the latest CentOS 5 image from the remote repository and cache it in the local index. If the image you are pulling is made up of layers, all of the layers will be pulled.

    docker pull centos

     

    List Images

    This will list all of the images in the local index and display how they are linked to each other. Every time a new container is spawned from an image, it will create another copy on write image to save it's changes too. The tree structure will help make things clear.

    Since, Docker 1.7, there is no native tooling to inspect image layers in a local cache, but with the help of a tool called dockviz, you can quickly inspect all of the layers in a local repository. The following command will returned shortened versions of the UUID that are typically unique enough to work with on a single machine. If you need to the full UUID, use the --no-trunc option.

    docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock nate/dockviz images -t

     

    Tag an Image

    It makes it easier to deal with images if they are tagged with simple names.

    docker tag fatherlinux/centos5-base centos5-base

     

    Run a Container

    Notice how easy it is to test a command in CentOS 4

    docker run -i -t -rm centos man rsync

     

    Log in to the Hosted Docker Registry

    To create repositories on the public Docker Registry, it is necessary to sign up at:

    https://www.docker.io/account/signup/

     

    Once you have created an account, you will need to login from the command line

    docker login index.docker.io

     

    If login is successful.

    Username: fatherlinux
    Password:
    Email: smccarty@redhat.com
    Login Succeeded

     

    Dockerfile: Commit an Image

    Once logged in to the public Docker Registry, new images can be built and committed with code using a Dockerfile. This allows an administrator to automatically rebuild a known good starting point quickly and easily. It is recommended to always start with an image defined by a Dockerfile.

    There are a couple of important things to notice with this Dockerfile. First, the FROM directive specifies centos as the base image. This will pull the latest image from the centos repostiory on DockerHub. In this example, I have provided the source repository for you. Second, the only change we have specified in the Dockerfile, is to update CentOS to latest available packages. Finally, notice we have a commented out ENTRYPOINT at the end of the file. Play with this option to get a feel for it while building from this Dockerfile.

    vi Dockerfile

     

    #
    # Version 1
    
    # Pull from CentOS RPM Build Image
    FROM centos
    
    MAINTAINER Scott McCarty smccarty@redhat.com
    
    # Update the image
    RUN yum update -y
    
    # Output
    # ENTRYPOINT tail /var/log/yum.log

     

    Build and tag the image

    Execute the following command in same directory as the Dockerfile.

    docker build -t centos-updated .

     

    Inspect the new image

    This will list all of the layers in an image

    docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock nate/dockviz images -t
    └─60e65a8e4030 Virtual Size: 196.6 MB Tags: docker.io/centos:latest
      └─6d8919b62698 Virtual Size: 196.6 MB
        └─05192ebc2b2d Virtual Size: 264.0 MB Tags: centos-updated:latest

     

    Notice that the new image is now available for deployment.

    Test the new image

    docker run -it --rm centos-updated tail /var/log/yum.log
    Jan 13 09:57:25 Updated: nss-sysinit-3.19.1-19.el7_2.x86_64
    Jan 13 09:57:26 Updated: nss-3.19.1-19.el7_2.x86_64
    Jan 13 09:57:27 Updated: nss-tools-3.19.1-19.el7_2.x86_64
    Jan 13 09:57:28 Updated: 1:openssl-libs-1.0.1e-51.el7_2.2.x86_64

     

    Manually: Commit an Image

    Once a container has changes made locally, they can be committed to the local index. This allows you to check point and continue. It also allows you to create new images based off of this modified container.

    docker run -it centos bash

     

    Modify the image

    Make some changes inside the container. In this example, create a test file and exit

    echo test file > /etc/test.cfg
    exit

     

    Commit the container

    First, get a list of containers. Notice that every container has a CONTAINTER ID and a STATUS. A status of Up means the container is currently running, while a status of Exit indicates that the container has been stopped. Think of the CONTAINER ID as a branch from the base image that contains all of the changes that were made to the container while it was running. By default this data is saved even after the container is shut down.

    docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                     PORTS               NAMES
    c65fe9f4194b        centos              "bash"                   About a minute ago   Exited (0) 3 seconds ago                       condescending_galileo
    620e24fc14c2        centos-updated      "tail /var/log/yum.lo"   6 minutes ago        Exited (0) 6 minutes ago                       determined_perlman
    ...

     

    Now, commit the container back as a branch of it's base image

    docker commit c65fe9f4194b

     

    Notice that the image is now available in the tree output. Also, notice that the newly created image layer (6d8919b62698) is a branch of the root centos:latest image, not the centos-updated:latest image, which we previously built with a Dockerfile.

    docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock nate/dockviz images -t
    └─60e65a8e4030 Virtual Size: 196.6 MB Tags: docker.io/centos:latest
      ├─5b6001fad9a6 Virtual Size: 196.6 MB
      └─6d8919b62698 Virtual Size: 196.6 MB
        └─05192ebc2b2d Virtual Size: 264.0 MB Tags: centos-updated:latest

     

    Tag the new image with something meaningful

    docker tag 5b6001fad9a6 centos-test

     

    Push a Container

    Once a container is committed locally, it can be pushed back to the registry server to be shared. The changes will be pushed as a layered image. Notice how quickly it is able to push only the differences between your modified image and the base image. This is a big part of the value.

    docker tag centos-test fatherlinux/centos-test
    docker push fatherlinux/centos-test
    The push refers to a repository [fatherlinux/centos-test] (len: 1)
    Sending image list
    Pushing repository fatherlinux/centos-test (1 tags)
    e39724bc32b2: Image already pushed, skipping
    c9bfb69481a8: Image successfully pushed
    Pushing tag for rev [c9bfb69481a8] on {https://registry-1.docker.io/v1/repositories/fatherlinux/centos6-base-hostname/tags/latest}

     

    Advanced Operations

    Pull All Standard Images

    These repositories (images) are publicly available from DockerHub and the Red Hat Registry.

    docker pull centos
    docker pull fedora
    docker pull registry.access.redhat.com/rhel

     

    Create Base Image

    This method was developed with guidance from this script. This example is based on CentOS 6.

    Create a tar file of the system

    tar --numeric-owner --exclude=/proc --exclude=/sys -cvf centos6-base.tar /

     

    Copy the tar file to where the consuming system and Import the image

    cat centos6-base.tar | docker import - centos6-base

     

    Test

    docker run -i -t centos6-base cat /etc/redhat-release

     

    Set Up a Registry Server

    Notice that the entire application is packaged up and ran from inside of a docker container. This has the interesting consequence that we are not even concerned with what operating system is hosting this registry application. Also, notice that port 5000 in the docker container is mapped to port 5000 on the hosting virtual machine, which makes the application running in the container transparently appear to be running on the virtual machine.

    docker run -p 5000:5000 registry

     

    Search Private Registry

    List all images in the repository

    http://registry.example.com:5000/v1/search?

     

    Search for all repositories with the word "rhel" in their name

    http://registry.example.com:5000/v1/search?q=rhel

     

    Remove Old Docker Containers

    By default, Docker keeps changes for every container which is instantiated. When testing, this can be undesirable. Be careful because this will remove all branches/data. Any containers which have not been committed will have all data deleted:

    docker rm `docker ps --no-trunc -a -q`

     

    Links

    • A Practical Introduction to Docker Container Teminology
    • Architecting Containers Part 1: Why Understanding User Space vs. Kernel Space Matters
    • Red Hat Enterprise Linux Atomic Host 7 Getting Started Guide
    • Running systemd within a docker container
    Last updated: February 22, 2024

    Recent Posts

    • How to use RHEL 10 as a WSL Podman machine

    • MINC: Fast, local Kubernetes with Podman Desktop & MicroShift

    • How to stay informed with Red Hat status notifications

    • Getting started with RHEL on WSL

    • llm-d: Kubernetes-native distributed inferencing

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue