- Fully customizable stack (Dockerfiles, stackfiles);
- Predictable load balancing (HAProxy);
- Cheaper then Heroku ($5 per instance at DO);
Containers for everybody
You have developed a small and dumb application and would like to host it at some nice place with a little effort. PaaS like Heroku have been doing it for you for last years. The problem is price, performance and management (Buildpacks meh). For example, tryflow.org was hosted on Heroku and it’s constantly failing because of strong memory consumption.
Cool concept, I need the implementation
Containers technology itself isn’t something new. Parallels has Virtuozzo for many years, I feel sad, though, community wasn’t yet ready for such thing at the time. But recently it has become a huge, huge^5, got funded, got every devops involved into this. And yet we have no common standard for containers. So I was about Linux containers (not Solaris or Windows, no kidding): raw LXC, LXD, CoreOS team trying Rkt and the most popular abstraction above LXC called Docker. I’ve choose Docker only because I’ve been already working with Docker since late 2013. The marketers also could say “Solid Ecosystem”, it means almost production-ready support by providers, every developer knows how to works with Docker, and so on.
To install Docker on OS X I use Homebrew and its addon Brew-cask - a nice way to install GUI apps via command line. Boot2docker requires VirtualBox, ensure you have it installed:
brew install caskroom/cask/brew-cask brew cask install virtualbox brew install boot2docker
So you have Docker client and Docker server which would be executed inside VM. If you into any Linux with modern core this is a way easier since docker has single executable. But if you are forced to emulate Linux on OS X, init and start virtual machine:
$ boot2docker init $ boot2docker up Waiting for VM and Docker daemon to start... .........................ooooooooooooooooooooooooo Started. Writing /Users/potomushto/.boot2docker/certs/boot2docker-vm/ca.pem Writing /Users/potomushto/.boot2docker/certs/boot2docker-vm/cert.pem Writing /Users/potomushto/.boot2docker/certs/boot2docker-vm/key.pem To connect the Docker client to the Docker daemon, please set: export DOCKER_HOST=tcp://192.168.59.103:2376 export DOCKER_CERT_PATH=/Users/potomushto/.boot2docker/certs/boot2docker-vm export DOCKER_TLS_VERIFY=1
Set the exports and you’re ready to go! You will see soon that 8GB RAM is definitely not enough for modern front-end web.
Choosing lightweight image
Docker use the abstractions called layers to be able build one images on top of another. The first line of most of Dockerfile started
FROM ubuntu:12.04, which means it use standard Ubuntu image. There is a holywar about multiprocess-in-a-container vs single-process-in-a-container and how properly OS should be fitted to be used inside container, which led to the birth of
docker-baseimage (Ubuntu + Docker-specific things). Cool, I love Ubuntu, but do I really need the entire 300mb image for running small node.js application? Nope. I’ve tried some images.
docker pull phusion/baseimage docker pull node docker pull iojs:onbuild docker pull ficusio/nodejs docker pull mhart/alpine-node docker pull joeandaverde/minimal-nodejs docker images REPOSITORY TAG CREATED VIRTUAL SIZE mhart/alpine-node 0.12 4 days ago 33.37 MB ficusio/nodejs latest 3 days ago 32.17 MB iojs onbuild 5 days ago 700.6 MB node latest 10 days ago 706.5 MB phusion/baseimage 0.9.16 11 weeks ago 279.7 MB phusion/baseimage latest 11 weeks ago 279.7 MB joeandaverde/minimal-nodejs latest 3 months ago 28.42 MB
Spoiler alert: the final size with node_modules is about 300 MB.
This is example of Dockerfile:
FROM mhart/alpine-node RUN apk update && \ apk add libc-dev gcc curl libgcc git && \ apk add python make ENV NODE_ENV PRODUCTION WORKDIR /src ADD . . RUN npm install --production RUN npm run postinstall EXPOSE 8080 CMD ["node", "app/server.compiled"]
Note: you can expose any port like 8080 and bind node to 80/443 later.
For different projects you might want to add different packages to this base image. For example, you need add to Python.
Choosing the clustering & orchestration layer
There a bunch of different Docker management tools, because Docker isn’t about service discovery, clustering, deploying, and so on. It doesn’t even worth name all of project, because every major cloud player already has something related to conatainers: Amazon, Google, Microsoft, Docker, and hundreds of others. Docker is great in terms of one container, but even you doesn’t want to scale you need to link, manage different containers across different machines. Look at the beautiful LastBackend, UI looks as the future from some cyberpank movie:
So managing containers is how you would manage your tech stack. After all, are you really full-stack developer, no matter what doesn’t this buzzword mean?
I use Tutum.co, because it’s simple, free and works well with DigitalOcean. But I’m sure in 2015 will be much more good alternatives.
Tutum uses the following terminology: Stacks, Services, Nodes.
To add Node simply link Tutum to your Cloud Provider to use API or install it to nodes manually.
To add Service push Image to Tutum’s private registry.
unknownexception is my username and
prism is a repository name. All this I’m doing from dev machine, but in real life images pushed from build server.
docker login tutum.co docker build -t unknownexception/prism . docker tag unknownexception/prism tutum.co/unknownexception/prism docker push tutum.co/unknownexception/prism
Using makefile, I just type
make deploy instead.
Once Image has pushed, you finally could create Service. It’s pretty obvious.
Started service will be available by endpoint, transparently balanced between several containters.
To redeploy just push the image again.