Skip to content

Instantly share code, notes, and snippets.

@jdhuntington
Last active December 15, 2015 22:52
Show Gist options
  • Save jdhuntington/77516d6a83aade398ea2 to your computer and use it in GitHub Desktop.
Save jdhuntington/77516d6a83aade398ea2 to your computer and use it in GitHub Desktop.

shipping with docker

Intro

Docker is a commercial project that supports running processes in isolated containers on machines. It’s the most popular brand associated with containers, but others do exist.

Lab

Goal: Start with a blank machine and deploy a web server, custom web application which talks to Redis, and Redis itself.

We’ll learn how to use off-the-shelf Docker images, build new docker images, and configure and run images.

Setup

Please do the following…

Provision a machine running Ubuntu Linux version 14.04 LTS

Should be a machine with at least 4gb RAM

Setting up the machine with SSH keys makes login easier, instructions are available at https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-windows-use-ssh-key/

When configuring networking, ensure ports 22, 80, 443, 8080, and 8081 are open.

Log into the machine with PuTTY

Download from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

If using with SSH keys (recommended), also download Pageant from the same location.

Update the machine

sudo apt-get update && sudo apt-get upgrade -y

Install Docker

This set of instructions[fn:1] will set up Docker Engine, the core of Docker.

sudo su - # enter root shell
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y linux-image-extra-$(uname -r)
apt-get install -y docker-engine
docker run hello-world

A bit about docker images

Our first real container: Redis

docker images
# see we have only hello world, now grab redis
docker pull redis
# now run docker images and see it exists
docker images
# next, start docker
docker run --name my-redis -d redis
# The printed value is the id of the container
docker ps
# If we telnet to the port, we can see that it's NOT listening.
telnet localhost 6379
# We'll need to start it again with a port mapping.
docker stop my-redis
docker rm my-redis
docker run --name my-redis -d -p 0.0.0.0:8080:6379 redis
# This means listen on all IPs on port 8080, and forward requests to redis port 6379

Run an app

We’ll build a new container to run a web app that utilizes the redis instance we just started.

The app is https://github.com/jdhuntington/effacious-adventure , a trivial todo list written in NodeJS.

For this we’ll be using docker build, which lets us script the creation of a docker image. This method is preferred over our previous interaction of logging in and running commands directly in a container.

Let’s make a new directory with a single file cakked Dockerfile.

mkdir my-app
cd my-app
touch Dockerfile
nano Dockerfile

And add this as the contents

FROM ubuntu
RUN apt-get update
RUN apt-get install git-core -y
RUN apt-get install nodejs -y
RUN apt-get install npm -y
RUN mkdir /var/app
RUN (cd /var/app && git clone https://github.com/jdhuntington/effacious-adventure.git)
WORKDIR /var/app/effacious-adventure
RUN npm install
EXPOSE 8081
ENTRYPOINT ["nodejs"]
CMD ["./app.js"]

Then, build the docker image with build. (It will probably take a few minutes.)

docker build .

Now that our image is built, it’s time to run the app inside of a container. We use docker run with the --link parameter to tell Docker that we want it to plumb details about the redis connection string to our new container.

In the example below, replace d198a0bef125 with the result of running docker build . in the previous step.

This will also bind the app to port 80 on our machine so that we can access it from any other machine (like your dev machine for example).

docker run --name my-node-app --link my-redis:redis -p 0.0.0.0:80:8081 -d d198a0bef125
docker ps

Wire up a proxy

A common means of hosting applications like the one we launched is to run them on a private port on a host, then use an application like nginx or HAProxy to expose it to the outside world. nginx or HAProxy can then be in charge of being hardened to the outside world, and handling details like SSL termination.

In this section, we’ll lean on another open source docker image which will launch nginx and handle the plumbing for us.

First, we’ll run this command to launch nginx as a reverse proxy[fn:2]:

docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
docker ps

Then we’ll launch our app again, this time with -e VIRTUAL_HOST passed as an argument. Grab the image ID from the last time this command was run.

This time we will not specify the port mapping. The nginx-proxy container will be doing the port mapping plumbing for us.

docker run --name my-node-app --link my-redis:redis -d -e VIRTUAL_HOST=jdhdockertest0.cloudapp.net d198a0bef125

Footnotes

[fn:1] The base for these instructions is https://docs.docker.com/engine/installation/ubuntulinux/ [fn:2] This is from the `usage` section of https://github.com/jwilder/nginx-proxy

FROM ubuntu
RUN apt-get update
RUN apt-get install git-core -y
RUN apt-get install nodejs -y
RUN apt-get install npm -y
RUN mkdir /var/app
RUN (cd /var/app && git clone https://github.com/jdhuntington/effacious-adventure.git)
WORKDIR /var/app/effacious-adventure
RUN npm install
EXPOSE 8081
ENTRYPOINT ["nodejs"]
CMD ["./app.js"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment