In case you were wondering, what the deal with CoreOS was: I wasn’t planning on leaving the stuff running as is, the idea is to actually run some containers. After wasting some 3 or 4 hours testing, here’s how to get your Meteor app running in Docker.
The setup
First off, you need a database. Meteor can use any database as long as it is MongoDB. Not my first choice, but after all, this is someone else’s baby that I’m setting up.
Setting up a MongoDB is pretty easy, due to the fact that a pre-made official
image is available which works pretty alright. Just do a
docker run -d --name db mongodb
and wait a few minutes, until the images
are loaded and set up.
Now, we want to run Meteor. I don’t have much experience with Meteor, but the
idea is that you compile everything to plain JS you can just run it via
Node.js. So, I took some inspiration from the
rocker-docker Dockerfile.
I put this stuff as Dockerfile
into my Git repo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
This starts off with the official Nodejs image, installs a newer Nodejs (since
Meteor needs at least 0.10.28 or so, which is newer than the node that is
packaged), installs Meteor and some helper packages. Then I am copying all the
Git repo contents to /meteorsrc
in the image. Not the cleanest location,
but I just wanted something quick that works. Then I run mrt install
which
presumably installs some Meteor stuff. The important part is meteor bundle
which creates a compiled copy of all Meteor resources in /var/www/app
that
can be served by Nodejs.
Then it is mostly environment variables and stuff. What is important is the
MONGO_URL
, as you notice it points not to localhost but to db
. Docker
isolates containers from each other, so the communication between containers is
kind of like between different hosts.
To create it, run docker build -t yourusername/reponame:tag .
which will
start the build. This might take a while. Afterwards I pushed it to the
Docker registry with docker push yourusername/repo:tag
, so I can get it to
the server in some more or less convenient way.
On the server, I did docker run -d -p 80:8080 --name web --link db:db yourusername/repo:tag
.
Let me explain that for a bit. What I do here is to run the container which I
just built, name it web
. The interesting part is the 80:8080
part which
means that whatever the server gets on port 80 will be forwarded to the Meteor
app running in the container on port 8080. Next, I am telling Docker to expose
the db
container (running MongoDB) to the new container using the db
alias. So the web
container can access db
via the hostname db
.
Observations
The idea with the containers is actually pretty neat, I like that setting up a MongoDB container requires zero setup and I can set up as many of them as I like without having to care about isolation. What I liked less is that the Nodejs container is outdated enough that I need to install a newer Node anyway, so what is even the point? I hope this will get fixed in the future. What I also didn’t like very much is that creating the image takes so long. Every step in the Dockerfile is another layer in the image and creating those takes way too long.
Next steps
I hope the node image will finally be updated to 0.10.29 or 0.10.30 which saves
me from a lengthy Node setup. I will also try to reduce the build times by
decreasing the amount of commands in the Dockerfile (PORT
is one obvious
candidate to be deleted). What I am also less than happy is the fact that I am
building the code on my laptop, then uploading the image to the Docker registry
(~250 MB, which takes a couple of minutes) and then download it again on my
server. Not sure what the best way to go about this will be, maybe setting up a
registry on the server, or maybe even building the image directly on the
server.
Also, the Docker user guide is rather pretty damn good. Need to read more.