Getting started with Concourse CI and Docker Part 2

Concourse CI & Docker blankWriting your own Dockerfiles and managing your Docker Images with Docker Hub

Welcome to the second part of our series about Concourse CI and Docker.
In the first one, you got a brief overview about Concourse CI in general and a very quick ‘getting started guide’ for Docker.

This time I will show you how to write your own Dockerfiles and push them to Docker Hub.
We will write a Dockerfile for a Docker Image to run a go example app.

Docker Images

Containers in Docker are launched from so called ‘Docker Images’. These images are read-only templates which consist of a series of layers. Docker then combines all of the layers to a single image. The layers are one of the reasons why Docker is so lightweight.
If you change something in an existing image, e.g. adding another application, or updating a version of an application, simply a new layer is built. That means you don’t have to replace the whole image or rebuilt it entirely, as you would probably do it with a virtual machine, the only thing is to add or update a specific layer.

Every Docker Image you can find starts from a so called base image, e.g. a base Ubuntu image, or a base Fedora image, however you can start from your own base images as well.

Docker Images are built from a Dockerfile, the place where all the instructions are stored. In the Docker world instructions include actions like:

  • Run a command
  • Add file or directory
  • Create environment variable
  • Process to run when launching a container from this image

Important to keep in mind that each of these actions will create a single layer in your Docker Image. We will show you how to prevent this in the next section of this post.

Dockerfile

Docker Images can be build automatically by reading the instructions from a Dockerfile. Because of this, it is good to know how to write a Dockerfile in order to build an image that will fulfill your needs.
Docker also provides best practices for writing Dockerfiles.

To start with your new Dockerfile you need a context for your work, that just means that you need a folder that contains all the things you may need to build your image, but enough of me talking, let’s get started and get our hands dirty.

Writing your first Dockerfile

To follow this guide you have to use the Docker Command Line by starting Docker Quickstart Terminal (In the first article you got to know how to get Docker Toolbox).
After starting the Docker Quickstart Terminal you get to know the IP-Address of the default machine, please take a note of this, we will need this later on.

  1. Create a new directory called „anynines_blog“
    mkdir anynines_blog
  2. Change to your new directory
    cd anynines_blog
  3. Create a new file „Dockerfile“
    touch Dockerfile
  4. open Dockerfile in a Texteditor
    open -e Dockerfile (MacOS) | nano Dockerfile (Linux) | notepad Dockerfile& (Windows)
  5. We will base our Docker Image on this Dockerfile Image.
    The „FROM“ keywords tells Docker which image will be your base image.
    type „FROM ubuntu:latest“
  6. install git and golang via apt-get
    RUN \
    apt-get update && \
    apt-get install -y git golang
    get our sample go app
  7. RUN \
    git clone https://github.com/anynines/a9s-go-example.git
  8. start the go web server on port 3000
    CMD PORT=3000 go run a9s-go-example/server.go
  9. Save the file
  10. Build the Dockerfile and name it anynines_blog
    docker build -t anynines_blog .
  11. Run the anynines_blog image and link port 3000 to port 3000 of the default machine
    docker run -t -i -p 3000:3000 anynines_blog

Now, you should see an output like PORT:3000, which means:, open your browser and browse to https://ip-of-your-default-machine:3000 (please enter the ip of your default machine) and press ENTER. If everything works fine you should see a white page with the word „Hello!“ on it.

If you write your RUN actions like in step 6 you prevent Docker from adding one layer for every apt-get command, in our case there is just one layer instead of two.

How to write a Dockerfile

Okay, the first Dockerfile is written. Cool stuff, but perhaps you feel like I did, when I tried to write my own Dockerfile for the first time.

How should I start? Which commands do I need? Is there a better way than writing a Dockerfile, building a Docker Image and hoping that everything is installed and will work?

Okay, this is for absolute beginners in writing Dockerfiles but hey, everybody has to start at some point.

Once again you need the Docker Quickstart Terminal

  1. Create a directory called „my_own_dockerfile“
    mkdir my_own_dockerfile
  2. Change to your directory
    cd my_own_dockerfile
  3. Create a new file „Dockerfile“
    touch Dockerfile
  4. open Dockerfile in a Texteditor
    open -e Dockerfile (MacOS) | nano Dockerfile (Linux) | notepad Dockerfile& (Windows)
  5. type „FROM ubuntu:latest“
    at this point you can use any other image you want to as your base image
  6. save the Dockerfile

Now, we got a very basic Dockerfile, this is our starting point.

  1. Now we build our Docker Image called „own_image“ from our Dockerfile
    docker build -t own_image .
    Please don’t forget the dot at the end
  2. Have a look at your current available images
    docker images
  3. Start a container based on your own_image with the command /bin/bash
    docker run -t -i own_image /bin/bash
  4. After that you are logged in to the shell of your container

Why do we need the command in 7. to run our container? This is because containers are designed to stop once the command executed within them has exited. That means that after exiting the bash, the container will get stopped.
To see all your current running containers you can enter „docker ps“ to the command line.
You are in the shell of your container based on your own Dockerfile, at this point you can install all the things you need and get to know which commands you have to write into your Dockerfile.

For example you want to ‘wget’ something in your container:

  1. Enter wget to the console and hit ENTER
  2. wget: command not found
  3. That means to us, we have to install wget first (good to know isn’t it?)
  4. Enter „sudo apt-get install -y wget“ into your container
  5. but also add the line „RUN apt-get install -y wget“ to your Dockerfile

Using line 5 you make sure that after updating the image based on your Dockerfile, a new layer is added, within this ‘wget’ is automatically installed. In this way you can build your Dockerfile until your container looks the way you want.

After that, you can build your finished Dockerfile and create a new image. Just make sure to delete the old image, since this does not happen automatically.

But wait, there’s one more alternative I want to mention here:

With this you will get a new image but not a Dockerfile

  1. docker run -t -i own_image /bin/bash
  2. run a container from our own_image again
  3. you will see something like that: root@85b13324ed65 (please take note of the container id 85b13324ed65 as you will need that in a moment)
  4. Install all the programs you need
  5. Exit the container with the command „exit“
  6. docker commit -m “Adding programs“ -a “Your name“ 85b13324ed65 image_name:imagetag

In line 6. we create a new image with the name ‘image_name’ and the tag ‘imagetag’ based on the container 85b13324ed65 (that’s the one we worked in).

Have a look at the list of your images now (docker images), you should notice the new created image.

With the command

[code language=”bash”]docker history image_id[/code]

you can see the commit messages of this image and which commands were used to build it.

Docker Hub

The Docker Hub is run and managed by Docker Inc. It is a place for centralized information about user accounts, images and public name spaces.

  1. Browse to Docker Hub and get yourself an account
  2. After you verified your email address, you will get redirected to the login mask of Docker Hub
  3. Enter your credentials and after hitting ENTER you can see your Dashboard

For more information about Docker Hub check out the Docker Hub Documentation.

Creating your first repository

Creating a repository is really easy; after logging in, you are redirected to your Dashboard, if not, just click on the ‘Dashboard’-Tab.

  1. Click on ‘Create Repository’
  2. Enter a name for your repository
  3. Enter a short description and a long description
  4. Choose the visibility ‘public or private’
  5. Hit ‘Create’

Done. You just created your first Docker Hub Repository and, believe it or not, we will use it right in the next section.

Push your image to Docker Hub

To make your images ‘pushable’ to Docker Hub they must be named after the following naming convention:

[code language=”bash”]docker_hub_user_name/docker_hub_repo_name[/code]

Don’t worry if you have just built an image at it does not follow this convention, you can change the name, or even better, you can get a new image with a specified name without building it from the Dockerfile again, yet using this command:

[code language=”bash”]docker tag image_id docker_hub_user_name/docker_hub_repo_name:tag[/code]

Please replace image_id by the image_id of the Docker image you want to rename and insert your Docker Hub Username and Repository Name for the placeholders.

Now, just one more command stands between us and our image being pushed to Docker Hub.

[code language=”bash”]docker push docker_hub_user_name/docker_hub_repo_name[/code]

If you got the error „unauthorized: access to the requested resource is not authorized“ please run first

[code language=”bash”]docker login[/code]

and then re-run the docker push command.

At this point of time, your Docker Image will be pushed to your Docker Hub Repository.
Well then, that’s enough for this time. In Part III we will start using Concourse CI and linking it with Docker Hub. That will be fun! I hope you enjoyed this one, see you next time!

<< Read part one  | Read part 3 >>

One thought on “Getting started with Concourse CI and Docker Part 2

  1. Pingback: Getting started with Concourse CI and Docker Part 4 | anynines blog

Leave a Reply

Your email address will not be published. Required fields are marked *