In the previous post, we pulled an image built by someone, and executed it, using commands such as:
docker run hello-world,
docker run ubuntu /bin/echo hello world or the more convoluted
docker run -d -p 8081:8081 -p 18078:18078 -p 18079:18079 --name nexus -v /data/nexus/nexus-data:/nexus-data sonatype/nexus3
In this post, we want to build our own image and publish it so someone else pulls it!
Docker image and how to build one?
As we already defined it,
A Docker image is an inert, immutable, file that's essentially a snapshot of a container. Images are created with the build command, and they'll produce a container when started with
In order to build a Docker image, we have to define a Dockerfile.
A Dockerfile is like a Makefile, containing build steps to build an image.
Anatomy of a Dockerfile
Let's look at a 'minimal' Dockerfile
FROM ubuntu:latest MAINTAINER Stratus Clay "email@example.com"
You can find the code under the stash repository docker-playground
FROMstep instruct Docker to inherit the base image, here ubuntu:latest, and then build on it
MAINTAINERstep, well, isn't mandatory after all ;), sets the author of the generated image
That's it when it comes to the 'minimal' Dockerfile
Let's build it now.
Building the image
In order to build the image, all we need to do is to execute in a shell in the Dockerfile directory:
docker build -t myimage:0.0.1 .
-tflag is used to tag the image. It is not mandatory, but you'll grow fond of it later on when you want to version your images.
Note that you can use the
-fflag to point to the Dockerfile if you do not want to
cdto it's directory.
You can attach multiple tags to the image (multiple repositories/versioning schemes...). e.g.:
docker build -t myimage:0.0.1 -t myimage:latest .
Let's list the images to see if we have what we built. To do that use the command:
REPOSITORY TAG IMAGE ID CREATED SIZE myimage 0.0.1 b8b64829e415 2 weeks ago 126.6 MB myimage latest b8b64829e415 2 weeks ago 126.6 MB
Testing the image
that's nice! Let's try to run our image now. we Can use
docker run for that.
But when we execute this particular image using the command, it seems that nothing happened:
docker run myimage:0.0.1
The "issue" here, is that the image is started without terminal and keyboard redirection. (Which is how a container is usually started). But Docker is nice enough to give us flag to control that.
-i -t or
-it is your friend here.
So, let's run "it" again with
docker run -it myimage:0.0.1
and now you should get a shell root access to the newly deployed container.
Execute in this shell any command to prove that it does what is supposed to: (is an Ubuntu in this case):
root@1b67d44e3d51:/# cat etc/os-release NAME="Ubuntu" VERSION="16.04.1 LTS (Xenial Xerus)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 16.04.1 LTS" VERSION_ID="16.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/" BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
All in all, we have with 2 lines in our Dockerfile created a new image based on a ubuntu latest (whatever that is at the moment).
Time to make our "valuable" image public for the world to see and build on!
Publishing the image
Let's try to do that without even thinking:
docker push myimage:0.0.1
The push refers to a repository [docker.io/library/myimage] 0cad5e07ba33: Preparing 48373480614b: Preparing 055757a19384: Preparing c6f2b330b60c: Preparing c8a75145fcc4: Preparing unauthorized: authentication required
Hmm. Let's try to authenticate:
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username:
OK. So here you can enter your docker hub id if you have one. (I suppose you already do now, so.)
Username: jmkhael Password: ***************** Login Succeeded
Let's try to push our image again now:
docker push myimage:0.0.1
Darn. It still doesn't work. That is because Docker Hub needs a special tag to link images to their authors.
docker tag myimage:0.0.1 jmkhael/myimage:0.0.1
Note that we could've used this tag when building the image:
docker build -t myimage:0.0.1 -t myimage:latest -t jmkhael/myimage:0.0.1 .
and now one more time, but with the new tag:
docker push jmkhael/myimage:0.0.1
The push refers to a repository [docker.io/jmkhael/myimage] 0cad5e07ba33: Pushed 48373480614b: Pushed 055757a19384: Pushed c6f2b330b60c: Pushed c8a75145fcc4: Pushed 0.0.1: digest: sha256:180b69c4655a1de392ab4a7f4c18705e50874dfae7b0c5e04cfaa size: 1357
Seems better :)
In this post (rather long):
- we created an image from scratch (with 2 lines)
- tested it (2 command) and
- made it public (2 commands)
In the next post, we will build us a first microservice contained, well, in a container.