3 min read

Meteor and Docker, with grigio/docker-meteor

Docker is very useful to build isolated environments for you applications, but Meteor is a quite particular software.

docker-meteor

Installation & running of a pinned Meteor version

❯ curl https://install.meteor.com/ | sh
❯ cd myapp && meteor

it means you can’t specify the meteor version that you need during the installation and running meteor will alwais looking for latest version available at runtime.

Here is a way to install a specific version of Meteor in a clean environment:

❯ export METEOR_RELEASE=1.0.2.1 # override the variable in the script that will be downloaded
❯ curl  https://install.meteor.com/ 2>/dev/null | sed 's/^RELEASE/#RELEASE/'| RELEASE=$METEOR_RELEASE sh
❯ cd myapp && meteor --release $METEOR_RELEASE

Why do I have meteor build client and server?

It isn’t clear for me why this command should be run on the client, because it include binaries that are architecture specific (Linux x86-64, OSX x86-64,..). So a bundled app in this way have to be rebuilt on the server to fix the wrong binaries.

If the server have the access to the application source code meteor build can be run just on the server.

Why do you have to install Node on the server?

if we have to run meteor build on the server, we need Meteor.

Meteor do not depends on Node, it embeds Node, so if you have to build your application on the server you need Meteor and you already have Node with it.

It isn’t guaranteed that Meteor will alwais work with latest NodeJS version, so it should be a best practise to use the same Node you used to develop that application (if you don’t want surprises).

Try this on a Linux system with already a version of Meteor installed:

❯ ls ~/.meteor/packages/meteor-tool/*/meteor-tool-os.linux.x86_64/dev_bundle/bin
BrowserStackLocal node npm

It means that you don’t have to install again node or npm, to install other deployment tools like demeteorizer, mup,.. You can just generate your app Docker image everytime your code changes or your dependencies changes and deploy that any instances you want.

You can use the same base image in development and production.

Development

As example we’ll use “meteor-sharejs demo” is like a simple Google Docs

❯ git clone https://github.com/mizzao/meteor-sharejs/
❯ docker pull grigio/meteor:1.0 # the same version used by the project demo
❯ sudo docker run -it -v $PWD/meteor-sharejs/demo:/app -p 1234:8080 grigio/meteor:1.0 /bin/bash
root@4bae180c01a0:/app# meteor --release $METEOR_RELEASE -p 8080
[[[[[ ~app ]]]]]                              

=> Started proxy.                             
=> Started MongoDB.                           
=> Started your app.                          

=> App running at: http://localhost:8080/

And you have the app running in the Docker sandbox at http://localhost:1234/ or http://your-docker-computer:1234/

Production

The meteor command used in development loads MongoDB, check the packages updates, watch the files for changes and much more, you don’t need that in production.

You need to create an image which contains meteor, the “bundled application” and also specify the environments variables that you need for the build. MONGO_URL and ROOT_URL are mandatory. You could also use the same Docker image with different variables.

Here’s recipe, create a Dockerfile like this inside the meteor application:

FROM grigio/meteor:1.0
MAINTAINER Your Name

# Add the source of your Meteor app and build
ADD ./demo /app 
RUN /meteor-build.sh

# Run the generated files
CMD /meteor-run.sh

Build your app image with:

❯ sudo docker build -t grigio/docker-meteor-demo .

An run it:

❯ sudo docker run -e "MONGO_URL=mongodb://172.17.0.4:27017/mytest" -e "ROOT_URL=http://example.com" -p 5555:8080 -it grigio/docker-meteor-demo sh /meteor-run.sh

And You’ll notice that this image will run almost instanly :)

grigio/docker-meteor is available as image in the Docker Hub and as source on Github.