Setting up your developer machine for Docker

Other posts in this series:  Docker for developers

This article will focus on setting up and using Docker from a developer perspective. If you are new to Docker, you might want to get up to speed quickly by reading this article. Without further ado, let's begin!

Setup Docker Toolbox

Download docker-toolbox for your environment. Just ONE tool to setup in order to avoid many other tools and software, eh? It will install the binaries for:

  • Docker Client
  • Docker Machine
  • Docker Compose
  • Kitematic (GUI for Docker)
  • Docker Quickstart Terminal

Docker client

Docker client relationship to the Docker daemon can be easily understood using the following image. As you can see, the Docker client talks to the daemon hosted on the VM and does what you ask it to.

To confirm Docker has setup correctly, check the output of the following command:

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b04784fba78d: Pull complete 
Digest: sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
<output snipped>

View all Containers

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
92a19e19c57f        hello-world         "/hello"            About a minute ago   Exited (0) About a minute ago                       boring_wright

Delete Containers & Images

You can delete containers and images by providing ID or name to the docker command. rm removes the container, and rmi removes the images. Containers, as you know... are the instantiation of the Images. And, as you can guess... you shouldn't remove the Images if your Containers are still in use. The following commands remove the Container followed by the Image.

$ docker rm 92a19e19c57f or docker rm 92a (the first few letters are enough)
$ docker rmi hello-world

Docker pull

docker pull is one of the commands that you will use a lot. You can search for various images from the Docker hub and simply download the image that you like. Super easy, and super cool!

## Pulling the latest image from docker-hub
$ docker pull kitematic/hello-world-nginx
Using default tag: latest
latest: Pulling from kitematic/hello-world-nginx
77c6c00e8b61: Pull complete 
9b55a9cb10b3: Pull complete 
e6cdd97ba74d: Pull complete 
7fecf1e9de6b: Pull complete 
6b75f22d7bea: Pull complete 
e8e00fb8479f: Pull complete 
69fad424364c: Pull complete 
b3ba6e76b671: Pull complete 
a956773dd508: Pull complete 
26d2b0603932: Pull complete 
3cdbb221209e: Pull complete 
a3ed95caeb02: Pull complete 
Digest: sha256:ec0ca6dcb034916784c988b4f2432716e2e92b995ac606e080c7a54b52b87066
Status: Downloaded newer image for kitematic/hello-world-nginx:latest

## View all images
$ docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
hello-world                   latest              1815c82652c0        2 months ago        1.84kB
kitematic/hello-world-nginx   latest              03b4557ad7b9        2 years ago         7.91MB

## Running the image on port 80 on the server and mapping it to internal port 80 for Nginx.
$ docker run -p 80:80 kitematic/hello-world-nginx
/website_files/index.html not found.
Copying default index.html...
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (2: No such file or directory)
2017/09/04 11:19:54 [notice] 6#0: using the "epoll" event method
2017/09/04 11:19:54 [notice] 6#0: nginx/1.4.7
2017/09/04 11:19:54 [notice] 6#0: built by gcc 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 r45973) 
2017/09/04 11:19:54 [notice] 6#0: OS: Linux 4.4.84-boot2docker
2017/09/04 11:19:54 [notice] 6#0: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2017/09/04 11:19:54 [notice] 6#0: start worker processes
2017/09/04 11:19:54 [notice] 6#0: start worker process 7

To find the IP of your docker server, you can run docker-machine ip default. Use a browser to hit the url and you should be able to see the page being rendered as:

Start another Docker terminal instance and run the following:

$ docker ps
CONTAINER ID        IMAGE                         COMMAND             CREATED             STATUS              PORTS                NAMES
b50d366e7d22        kitematic/hello-world-nginx   "sh /"      12 minutes ago      Up 12 minutes>80/tcp   happy_turing

To stop this container use: docker stop b50d366e7d22 or docker stop b50 (first few characters are enough).

Just imagine the power of docker pull. This tiny command has pulled a server for you from the internet, that has Nginx installed and working! Not only that, you can use docker rm and docker rmi commands to delete the images and containers ==completely==! As a developer, this comes in really handy since you can play around as much as you like with different software and clean them up without leaving any mess created by the installed software on your local machine behind.

Map a Volume to your source code

So, you have a Docker VM running containers and you are able to download interesting software easily and work with it. Now what? Let's take it to the next level by hooking your own source code to Docker containers.

The reason why you wouldn't write to the container layer directly is because the data will be lost if you delete the container. Volumes help you overcome this issue and are fairly simple to create. Let's do it, step-by-step.

Step 1: Create a sample app using Express

$ mkdir /path/sample
$ cd /path/sample
$ express
 create : .
   create : ./package.json
   create : ./app.js
   create : ./public
   create : ./public/javascripts
   create : ./public/images
   create : ./routes
   create : ./routes/index.js
   create : ./routes/users.js
   create : ./public/stylesheets
   create : ./public/stylesheets/style.css
   create : ./views
   create : ./views/index.jade
   create : ./views/layout.jade
   create : ./views/error.jade
   create : ./bin
   create : ./bin/www

   install dependencies:
     $ cd . && npm install

   run the app:
     $ DEBUG=Testing:* npm start

Step 2: Install dependencies and start

Start by executing npm install followed with npm start. You should be able to view the basic setup using http://localhost:3000.

Step 3: Set current directory as a Volume in a Docker container!

Use the following command to map a volume inside container to the current directory.

$ docker run -p 80:3000 -v $(pwd):/web/express -w "/web/express" node:4.8 npm start
  • -v switch uses $(pwd) to suggest Docker to create a link to the current folder.
  • /web/express is just a convention, suit yourself!.
  • node:4.8, node, node:latest are some of the ways in which you can specify which Node version are you interested in.
  • The command npm start tells docker which command to execute in the container.
  • You can set the working directory using -w switch.

Step 4: Test your App

Browse to http://docker-machine-ip/ and you should be able to see your page successfully. Notice the absence of port in the URL. That is because while mapping the container we said public port 80, maps to internal port 3000.

List Volumes of a container

If you have a running container and want to figure out the existing mount points, you can use the following approach:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
994de8c1137b        node:4.8            "npm start"         29 minutes ago      Up 29 minutes>3000/tcp   hopeful_tesla

$ docker inspect 994de8c1137b

## Scroll up and navigate to Mounts
        "Mounts": [
                "Type": "bind",
                "Source": "/Users/your_profile/Desktop/Testing",
                "Destination": "/web/express",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"

Manage virtual machines using docker-machine

If you are using Docker on a Mac or Windows, it creates a VM for you automatically called default. You can create more VMs if you like. To manage these VMs locally or in the cloud you can use docker-machine.

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
default   *        virtualbox   Running   tcp://           v17.07.0-ce   

$ docker-machine stop default
Stopping "default"...
Machine "default" was stopped.

$ docker-machine start default
Starting "default"...
(default) Check network to re-create if needed...
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

$ docker-machine env
export DOCKER_HOST="tcp://"
export DOCKER_CERT_PATH="/Users/ rahul sonisoni/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell: 
# eval $(docker-machine env)

$ docker-machine status default

==TIP: You may see a normal terminal like docker ps error out saying: Cannot connect to Docker daemon. It is simply complaining about your terminal not initialising the Docker env variables and a little plumbing. Run the following commands on any terminal and you will be all set if your VM is running. You can use these commands to connect to different VMs on different terminals simultaneously. You face this error, if you use Docker Terminal provided by Docker toolbox. ==

$ docker-machine env default
export DOCKER_HOST="tcp://"
export DOCKER_CERT_PATH="/Users/ rahul sonisoni/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell: 
# eval $(docker-machine env default)

$ eval $(docker-machine env default)

Try again and you will find docker ps yielding results.

What next?

Well, stay tuned for upcoming articles. You may contact us at for your software and consultancy requirements.

© 2023, Attosol Private Ltd. All Rights Reserved.