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.
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.
Please do the following…
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.
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.
sudo apt-get update && sudo apt-get upgrade -y
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
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
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
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
[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