Docker, an application-container distribution automation software using Linux-based virtualization, has gained a lot of momentum since it was released in 2013. I never had a chance to try it out but a current project has prompted me to bubble it up my ever-growing To-Do list. Below is a re-cap of my first two hours of experimenting with Docker.
First thing first, get a quick grasp of Docker’s basics. I was going to test it on a MacBook and decided to go for its beta version of Docker for Mac. It’s essentially a native app version of Docker Toolbox with a little trade-off of being limited to a single VM, which can be overcome if one uses it along side with Docker ToolBox. The key differences between the two apps are nicely illustrated at Docker’s website.
Downloading and installing Docker for Mac was straight forward. Below is some configuration info about the installed software:
# Show info docker info ... Server Version: 1.12.0-rc2 Storage Driver: aufs Root Dir: /var/lib/docker/aufs Backing Filesystem: extfs Dirs: 87 Dirperm1 Supported: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: null host bridge overlay Swarm: inactive Runtimes: default Default Runtime: default Security Options: seccomp Kernel Version: 4.4.13-moby Operating System: Alpine Linux v3.4 OSType: linux Architecture: x86_64 ... # Show version docker version Client: Version: 1.12.0-rc2 API version: 1.24 Go version: go1.6.2 Git commit: 906eacd Built: Fri Jun 17 20:35:33 2016 OS/Arch: darwin/amd64 Experimental: true Server: Version: 1.12.0-rc2 API version: 1.24 Go version: go1.6.2 Git commit: a7119de Built: Fri Jun 17 22:09:20 2016 OS/Arch: linux/amd64 Experimental: true
Next, it’s almost illegal not to run something by the name of hello-world when installing a new software. While at it, test run a couple of less trivial apps to get a feel of running Docker-based apps, including an Nginx and a Ubuntu Bash shell.
# Run hello-world docker run hello-world # Run Nginx in background exposing port 80 docker run -d -p 80:80 --name webserver nginx # Run Ubuntu Bash interactively on a tty terminal docker run -it ubuntu bash # Show all containers docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ee8917ebea6e ubuntu "bash" 48 seconds ago Exited (0) 24 seconds ago stoic_payne 795a36227667 nginx "nginx -g 'daemon off" 24 minutes ago Up 24 minutes 0.0.0.0:80->80/tcp, 443/tcp webserver 89de18ed6afd hello-world "/hello" 41 minutes ago Exited (0) 41 minutes ago silly_fermi
While running hello-world or Ubuntu shell is a one-time deal (e.g. the Ubuntu shell once exit is gone), the -d (for detach) run command option for Nginx would leave the server running in the background. To identify all actively running Docker containers and stop them, below is one quick way:
# Show all running containers docker ps -q 795a36227667 # Stop all running containers docker stop $(docker ps -q) # Show all images docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest 693bce725149 2 weeks ago 967 B nginx latest 0d409d33b27e 2 weeks ago 182.8 MB ubuntu latest 2fa927b5cdd3 3 weeks ago 122 MB
It’s also almost illegal to let any hello-world apps sitting around forever, so it’s a perfect candidate for testing image removal. You’ll have to remove all associated containers before removing the image. Here’s one option:
# Remove all containers associated with hello-world docker ps -a | grep hello-world | awk '{print $1}' | xargs docker rm # Remove image hello-world docker rmi hello-world
Note that the above method only remove those containers with description matching the image name. In case an associated container lacking the matching name, you’ll need to remove it manually (docker rm
Adapted from Linux’s Cowsay game, Docker provides a Whalesay game and illustrates how to combine it with another Linux game Fortune to create a custom image. This requires composing the DockerFile with proper instructions to create the image as shown below:
# Download and run Whalesay docker run docker/whalesay cowsay boo # Create a subdirectory for image building cd ~/projects/docker/ mkdir dockerbuild cd dockerbuild/ # Create Dockerfile vi Dockerfile FROM docker/whalesay:latest RUN apt-get -y update && apt-get install -y fortunes CMD /usr/games/fortune -a | cowsay :wq # Build Docker image fortune-whalesay docker build -t fortune-whalesay . Sending build context to Docker daemon 2.048 kB Step 1 : FROM docker/whalesay:latest ---> 6b362a9f73eb Step 2 : RUN apt-get -y update && apt-get install -y fortunes ---> Running in 6f41bac87627 Ign http://archive.ubuntu.com trusty InRelease Get:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB] Get:2 http://archive.ubuntu.com trusty-security InRelease [65.9 kB] Hit http://archive.ubuntu.com trusty Release.gpg Hit http://archive.ubuntu.com trusty Release ... Setting up librecode0:amd64 (3.6-21) ... Setting up fortune-mod (1:1.99.1-7) ... Setting up fortunes-min (1:1.99.1-7) ... Setting up fortunes (1:1.99.1-7) ... Processing triggers for libc-bin (2.19-0ubuntu6.6) ... ---> 723b1dc99873 Removing intermediate container 6f41bac87627 Step 3 : CMD /usr/games/fortune -a | cowsay ---> Running in f0edad30afa2 ---> a6bd063431a4 Removing intermediate container f0edad30afa2 Successfully built a6bd063431a4 docker images REPOSITORY TAG IMAGE ID CREATED SIZE fortune-whalesay latest a6bd063431a4 36 minutes ago 274.6 MB nginx latest 0d409d33b27e 2 weeks ago 182.8 MB ubuntu latest 2fa927b5cdd3 3 weeks ago 122 MB docker/whalesay latest 6b362a9f73eb 13 months ago 247 MB docker run fortune-whalesay / A pound of salt will not sweeten a \ \ single cup of tea. / ------------------------------------ ...
Next, to manage your Docker images in the cloud, sign up for an account at Docker Hub. Similar to GitHub, Docker Hub allows you to maintain public image repos for free. To push Docker images to your Docker Hub account, you’ll need to name your images with namespace matching your user account’s. The easiest way would be to have the prefix of your image name match your account name.
For instance, to push the fortune-whalesay image to Docker Hub with account name leocc, rename it to leocc/fortune-whalesay:
# Rename an image (first add a tag then remove old tag with rmi) docker tag fortune-whalesay leocc/fortune-whalesay docker rmi fortune-whalesay # Push image to Docker Hub docker login -u leocc docker push leocc/fortune-whalesay
Finally, it’s time to try actually dockerize an app of my own and push it to Docker Hub. A Java app of a simple NIO-based Reactor server is being used here:
# Dockerize Java app NIO-Reactor # Designate a build subdirectory and copy Java source code cd ~/projects/docker/dockerbuild/ mkdir reactor cp -p ~/projects/jstuff/reactor/src/reactor/*.java reactor/ # Create .dockerignore vi .dockerignore .DS_Store .DS_Store? ._* :wq # Create Dockerfile vi Dockerfile FROM java:8 COPY . /tmp WORKDIR /tmp EXPOSE 9090 RUN javac reactor/*.java RUN jar -cf reactor/nioreactor.jar reactor/*.class CMD java -classpath reactor/nioreactor.jar reactor.Reactor :wq # Build image docker build -t leocc/nioreactor . # Test run Dockerized app docker run -t -p 9090:9090 leocc/nioreactor # Test the NIO Reactor server from a telnet client telnet localhost 9090 # Push image to Docker Hub docker login -u leocc docker push leocc/nioreactor
The Dockerized Java app is now at Docker Hub. Now that it’s in the cloud, you may remove the the local image and associated containers as described earlier. When you want to download and run it later, simply issue the docker run command.
My brief experience of exploring Docker’s basics has been positive. If you’re familiar with Linux and GitHub, picking up the commands for various tasks in Docker comes natural. As to the native Docker for Mac app, even though it’s still in beta it executes every command reliably as advertised.