Friday, May 15, 2015

Series: How to create your own website based on Docker (Part 6 - Creating Ubuntu Base Image)

Creating our Ubuntu Base Image

This is part 6 of the series: How to create your own website based on Docker.

Before we can run a Docker container, we need to create a Docker image. So why is that? Well, Docker images are read-only templates to create Docker containers and these images define everything Docker needs to know to create containers (you can run several containers based on the same image).

In this part of the series, we're going to create the base image for all our other images (as they should all run on Ubuntu). This image will be a basic Ubuntu image that brings all the software/tools/drivers that is going to be needed by all images depending on it - that's why I'm calling it the "base image".

Source code

All files mentioned in this series are available on Github, so you can play around with it! :)

Using the official Ubuntu Base Image

There are two cool things that Docker provides and we will make use of:
  • You can use the Docker Hub to get already created images (you can also upload your image to Docker Hub, but we're not doing it here).
  • Whatever we install/set up in our Ubuntu image,can be reused in all other containers that are built on this base image - so these settings are shared among all other containers that are based on that image.
Important notice: When running servers in production I do always recommend to use official images as base image, since you can't be sure if some bad guy added some malicious stuff to that image and let's be honest, it's much cooler to create the image yourself! To get a list of available (official) images, just visit the Docker Hub Registry.

For our projectwebdev website we're using the official Ubuntu image and will add our custom software and settings. You will see that the steps we're doing now are pretty much the same every time, so I'll write them down more generic first, before we get into details:
  1. Create a directory within your Docker directory (in our case that would be /opt/docker/ubuntu-base).
  2. Create a Dockerfile (the template that describes the image) within that new directory (so the file would be /opt/docker/ubuntu-base/Dockerfile).
  3. Create additional directories that contain either scripts or config files that should be added to the image/container.
  4. Create additional directories to act as volume mounts for the containers.
As mentioned before, we're going to use the official image and will then install the software that will be needed by all containers that are based on that image. So let's create our Dockerfile (/opt/docker/ubuntu-base/Dockerfile) by adding the image to pull from the Docker Hub.

Get the base image

If we want to use the latest available Ubuntu distribution, we can type something like this:
# Pull base image.
FROM ubuntu:latest
In our case that would be Ubuntu 15.04 (Vivid Vervet), but I'll always recommend to specify the version number explicitly so we don't get surprised with a new Ubuntu version, as soon as we build our images after October when Ubuntu 15.10 (Wily Werewolf) is released.
# Pull base image.
FROM ubuntu:15.04
As you can see here, there are more versions of Ubuntu available, so you can also pull Ubuntu 14.04 LTS (Trusty Thar) from the hub.

Install all needed packages

Since we're working with several technologies later, it's good to have a solid software base under the hood. That's why I've installed the following packages in my base image, just to make sure they are available:
  • build-essential
  • curl
  • git
  • man
  • software-properties-common
  • unzip
  • vim
  • wget
I do always run apt-get update and apt-get dist-upgrade every time I build my images, to make sure that I'm on the latest packages, whenever I rebuild everything - I also clean up some space by deleting all unnecessary package stuff.

So the second part of our Dockerfile looks like this:
# Install the software/packages needed for all other containers
RUN \
  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
  apt-get update && \
  apt-get -y upgrade && \
  apt-get install -y build-essential software-properties-common curl git man unzip vim wget && \
  rm -rf /var/lib/apt/lists/*

Setup some variables and run

The next step is to set an environment variable (ENV) and a WORKDIR (sets the working directory for the following CMD instruction).
# Set environment variables.
ENV HOME /root 
# Define working directory.
WORKDIR /root
No we're telling our image what command to run when the container is started - in our case that would be bash:
# Define default command.
CMD ["bash"]
That's it - that's our Dockerfile - so here it is completely:
# Pull base image.
FROM ubuntu:15.04
# Install the software needed for all other containers
RUN \
  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
  apt-get update && \
  apt-get -y upgrade && \
  apt-get install -y build-essential software-properties-common curl git man unzip vim wget && \
  rm -rf /var/lib/apt/lists/*
# Set environment variables.
ENV HOME /root
# Define working directory.
WORKDIR /root
# Define default command.
CMD ["bash"]
Source: https://github.com/mastix/project-webdev-docker-demo/blob/master/ubuntu-base/Dockerfile

Testing the Ubuntu Base Image/Container without Docker Compose

You can basically test you new container without using Docker Compose. First build you new image like this:
# cd /opt/docker/ubuntu-base
# docker build -t projectwebdev/ubuntu-base .
Result:
Sending build context to Docker daemon 3.584 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:15.04
15.04: Pulling from ubuntu
b68f8c8d2140: Pull complete
1d57666667e5: Pull complete
a216ec781532: Pull complete
bd94ae587483: Already exists
ubuntu:15.04: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:6994d0f1e915ff22a9b77433c19ce619eda61e5a431a7ba89230327b2f289a95
Status: Downloaded newer image for ubuntu:15.04
 ---> bd94ae587483
Step 1 : RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list &&   apt-get update &&   apt-get -y upgrade &&   apt-get install -y build-essential &&   apt-get install -y software-properties-common &&   apt-get install -y byobu curl git htop man unzip vim wget &&   rm -rf /var/lib/apt/lists/*
 ---> Running in 2d49adfb4fce
Ign http://archive.ubuntu.com vivid InRelease
Ign http://archive.ubuntu.com vivid-updates InRelease
[...]
Step 2 : ENV HOME /root
 ---> Running in 1923ed0e21a0
 ---> a5b574f11a0f
Removing intermediate container 1923ed0e21a0
Step 3 : WORKDIR /root
 ---> Running in 4bfbeeea1733
 ---> dff8fc1d0b06
Removing intermediate container 4bfbeeea1733
Step 4 : CMD bash
 ---> Running in 6b086dd626ac
 ---> cfad3f94c992
Removing intermediate container 6b086dd626ac
Successfully built cfad3f94c992
Now we can run our container and connect to bash (remember that we have set bash as CMD in our Dockerfile):
# docker run --name ubuntu-base-test -t -i projectwebdev/ubuntu-base
Here's the result - we've been able to trigger commands withing our new Ubuntu container - I've also called env to show you the environment variable HOME that we have set:
# docker run --name ubuntu-base-test -t -i projectwebdev/ubuntu-base
root@06913990a3c8:~# env
HOSTNAME=06913990a3c8
[...]
HOME=/root
[...]

Cleanup image file and docker container

Since this was just a basic test, we'll have to remove the image and the container to save some space.
# docker rm -f ubuntu-base-test
# docker rmi -f projectwebdev/ubuntu-base
That's it! Our Ubuntu base image is up and running and can therefore be started via Docker Compose. Let's create the mongodb container in the next part!

10 comments:

  1. Sascha,
    I realize what I didn't understood. About this command:

    # docker build -t projectwebdev/ubuntu-base .

    What everyone needs to understand is that `projectwebdev/ubuntu-base` is a TAG you defined (not a path!) where projectwebdev is your docker hub user and ubuntu-base is the tag's name. The dot at the end execute our Dockerfile.

    Now...
    I have this issue. Docker deamon is lost :-/

    dev@ubuntu:/opt/docker/projectwebdev/ubuntu-base$ docker build -t projectwebdev/ubuntu-base .
    Cannot connect to the Docker daemon. Is the docker daemon running on this host?
    dev@ubuntu:/opt/docker/projectwebdev/ubuntu-base$ docker -v
    Docker version 1.10.1, build 9e83765
    dev@ubuntu:/opt/docker/projectwebdev/ubuntu-base$

    Hope you can help :-)

    Cheers!
    Pascal

    ReplyDelete
    Replies
    1. My bad ! I did overcome the folling steps:

      1) Create a directory within your Docker directory (in our case that would be /opt/docker/ubuntu-base).

      2) Create a Dockerfile (the template that describes the image) within that new directory (so the file would be /opt/docker/ubuntu-base/Dockerfile).

      Now I can move on :)

      Delete
  2. Great information thanks for sharing this with us.In fact in all posts of this blog their is something to learn . your work is very good and i appreciate your work and hopping for some more informative posts .
    Web Development

    ReplyDelete
  3. What a response, that's what I was looking for, thanks to a friend!

    ReplyDelete