Docker: team up to create a reference docker image for meteor

I think having two different images for development and production is absolutely the way to go. But having identical environments is key for Docker Images, so I’d propose to build up a graph like this:

alpine-node
-> alpine-meteor

    • alpine-meteor-development (installs meteor with curl, “devbuild” way, starts with meteor + args + env)

The way @martinezko solved the “production-runtime” problem is really cool I think but it depends on a direct version of node where as every meteor version could possibly demand for another version.

I tried to pull out all of the scripts and simplify it for my needs + having the possibility to specify the node & npm version during build time (not pushed to docker, just a poc): https://github.com/pozylon/meteor-docker-runtime/blob/master/Dockerfile

As you can see node and npm version is specified as ENV. I think that we’ll propably need some kind of very small CLI which actually allows for generating the production Dockerfile and the bundle for simplicity:

fireball init --server=https://asdfasdf:443

  1. Initializes a .deploy folder if it does not exist.
  2. Takes all the arguments passed and pass it to meteor build, if --architecture is not provided, add it. build it into ./.deploy/*.tar.gz
  3. Runs meteor npm --version & meteor node --version inside the meteor app’s folder to find out how exactly we have to build the underlying node environment.
  4. Add a new Dockerfile to .deploy, looking something like, or just update the ENV’s to match the current versions:
    ’’‘
    FROM alpine-meteor-production
    ENV NODE_VERSION=XYZ
    ENV NPM_VERSION=XYZ
    ’’’

fireball build [–repository]

  1. docker build inside .deploy tagging with package.json information: [repository]/MAINTAINER-APP_NAME:APP_VERSION

With the work that abernix started with his v2 image, we could even go further and offload testing/building into a DIND/docker.socket link environment, spinning up a container which actually builds the bundle ^^ What do you guys think?

1 Like

Hey i have my own dummy script to do this:

dummy repo

Its not a complete CLI or something like that… is just a folder i paste on each of my projects, then i clone it on my servers and run them… voilá… running meteor!

@kaufmae that’s really great work. Thanks for contributing. I think that for this to be adopted by the community, we need to cover a couple of use-cases.

  1. Be compatible with MUP. (It’s not my use case. But if we can’t be compatible with MUP it will not become the standard/reference meteor docker image).

  2. Allow the dev build ( alpine-meteor-development) to also host the app ( for people who don’t care about image size, but want the convenience of dockerhub running an automated build)

  3. Should be backwards compatible with other meteor versions. ( It seems like your build can do this, can you clarify).

Thanks in advance for the initiative of setting up an alpine image!

Mup isn’t compatible with itself from version to version, actually the same people are developing at least 2 versions (mup and mupx) that you need to use with different meteor version…

so if I find something more robust/reliable/longlasting with the same or similar caracteristic I’m switching ASAP!

I like this idea. Most production apps (mine included) are running the app in one place and the database in another. So this would make for a better reflection of what things are like in production.

containers for mongo, nginx, and meteor

I would also love to figure out how to set this up through Vagrant. That way any machine can have the same setup. My team has developers using Linux, Windows, and Mac, so Vagrant is a necessity

I use docker-compose, and my development and production environments are as similar as possible. The only difference is that, by tweaking the development dockerfile, I can run the ‘meteor’ command in development and node in production.
So I get hot code reload while I’m developing, in an environment that is very similar to production.
So I’m very keen on the two flavors that have been proposed here.

And I also fiddle with nginx in its own container in the knowledge that it will work basically the same in production.
My particular database setup is however not recommended. As you say, using a remote database is clearly the way to go, and mine is not remote.
But I have a pretty small app with a tiny database backed up regularly so nobody gets hurt.
And my client (me) cannot afford a remote database unless the site starts earning money.

Credits go to @martinezko about the alpine meteor thing. I just copy pasted the most essential parts from his image and from alpine-node.

1 Like

My problem with MUP is that it tries to setup and deploy everything in it’s very own blackbox style. The whole MUP process could be solved by using all docker native technologies:

install mup:

  • curl script downloading and installing docker toolbox + symlink

mup setup:

  • (docker-machine create)
  • docker-machine env
  • docker-compose up -d (nginx, letsencrypt-nginx, nginx-gen, logrotate, mongodb, appname)
    Result:
    docker-machine env dump: ./.deploy/.docker-machine
    docker-compose configuration: ./.deploy/docker-compose.yml
    docker file: ./.deploy/Dockerfile

mup deploy:

  • docker build
  • docker pull

mup reconfig:

  • docker-compose up -d appname

The biggest advantage of such a new cli would be that you can step in everywhere and only use what you need.

  • Use the new tool to provision a docker-machine and all the clever sidecontainers with the generic driver on bare-metal
  • Use the new tool to provision all the containers on an existing docker engine by “docker-machine env my-engine > .docker-machine” or just don’t set it and use the local docker engine.
  • Use the new tool to build your app for docker usage
  • Use the new tool to prepare everything then add imagemagick to the Dockerfile because the app needs it.

I’m not defending MUP. It’s broken in many ways.

What I am saying is: that if we want a de-facto/reference/recommended meteor docker implementation, we need to involve the MUP community. Otherwise we will continue having fragmented images.

I don’t think it’s actually too difficult to accomplish most of the goals:

  • If we start with abernix/meteord (has dev and prod options, and already works with MUP and dockerhub builds)
  • include @jeremy changes to root user, and meteor versioning, adding binaries like imagemagick, phantomjs.
  • change debian for @martinezko alpine implementation.
  • add tests as @sashko volunteered to do.

This might get us very close. A CLI is optional. I would just build my image directly on dockerhub. But others could use a lightweight CLI like @kaufmae is suggesting (in dev or CI server).

1 Like

I agree with you, and with your considerations.

Maybe we can agree on something like “guidelines” so the developers have the necessary references to work, for example minimum requirements like: (this is just an example, I know that all of this is already supported) “hey, the tool have to support the public key authentication for ssh, install CERN httpd and download 3 different photos of a black cat”.

I made my deploy script myself but it’s far from optimal and doesn’t cover all use cases, we are fundamentally reinventing the wheel everytime here.

Then we can just do pull-request to implement more specifications as everyone need them (I very often need ssh to connect to local tunnel so using non standard ports, just for example)

But it will be good to have a tool that will not break every two meteor releases :smiley:

ask him on github.
my image is currently 905 MB

I think you were confused. I don’t see anything about GridFS bein abandoned

Yep, I was thinking of https://github.com/aldeed/Meteor-CollectionFS

For what it’s worth, as long as you’re using Meteor 1.4.2.1 (and not exactly Meteor 1.4.2 due to a bug in core) or Meteor 1.4.1.3, my abernix/meteord image (including the :onbuild tag) should be working once again. I’ve also updated it to Node 4.6.2.

I’ve also pushed out abernix/spaceglue to Docker Hub which is now a complete re-write of abernix/meteord (which was a hacked-together version of meteorhacks/meteord). This was what I had previously mentioned was in my v2 branch on abernix/meteord. It turns out the changes were significant enough to get a new name, even if there is still some similar functionality, because there is no way it could reconverge with the master branch. It has a several advantages over /meteord.

SpaceGlue:

  • Is smart enough to download the exact version of Meteor necessary when building (previously, the latest published release PLUS the version your app needed had to be downloaded – this was mainly just slow).
  • Has a smaller footprint (The base is almost half the size around ~250mb. The builddep images are bigger, but still smaller than meteord – I’m sure there’s room for improvement)
  • Adds a lot of tests to facilitate updates – I’d have confidence in accepting a pull-request now if the tests work on CircleCi. :slight_smile:
  • Deploys new versions (of the Docker image) automatically to Docker Hub via CircleCI after tests pass successfully (does not use Docker’s Build system though since it doesn’t support a clean nested tag dependency system)
  • Does not run node as root (long-overdue for security reasons)
  • Should re-build any binary dependencies with less problems (by providing better node-gyp build dependencies)
  • Will work with Kadira’s Meteor Up if one change gets accepted (already PR’d). I tried to avoid this change being necessary and keep things on port 80, but due to variations in allowed kernel capabilities, I couldn’t. Specifically, due to ongoing, back-and-forth issues with supporting the net_bind_service cap, this isn’t possible. Plus, even if it was implemented, many users still use Docker 1.9 or earlier and it will take some time to update them all.

In regards to the question(s) of combining efforts… again, I’m all for it, but I’d want a clear plan and small actionable items to help with that. I will happily review and accept pull-requests, but I have a lot of other things I’m taking care of. (Slash, sorry I just created another Docker image, but that seems to be the common theme in this issue anyhow :slight_smile:).

4 Likes

@abernix that seems like amazing progress. Especially having a CI testable image.
I’m going to experiment with it asap. Do I just run it like meteorD?

I know some people will ask about phantomjs and imagemagick dependencies (not my case).

Can you expand on the MUP issue? It’s also also not my case, but I’m sure someone would ask for it.

1 Like

There is a README that explains how to use it. But essentially, yes. Let me know how it goes for you!

Well, not really. The reason is above. :slight_smile:

In some future version of Docker (1.14, they claim now) it may not be necessary to land my PR with Meteor Up, but as it stands right now it’s not possible to run on port 80 as an unprivileged user without some problem popping up on one storage driver or another. This is the only reliable way right now. No matter what happens, it would still be better to land that PR so that Docker images with different exposed ports could be used.

If PhantomJS is necessary, the developer should use the phantomjs-prebuilt NPM in their project just like any other NPM. The binary will be available in node_modules/.bin/phantomjs and they can set PHANTOMJS_BIN in their environment to that path and most tools will use it automatically .

I find it unlikely that I will consider an option to built-in PhantomJS. It’s not necessary since it can be included at the app-level. I imagine there is something similar available for imagemagick.

@abernix,
Thanks for making great documentation in a short time ( I hadn’t seen it the first time, I accessed it).

@arunoda any opinions on the pull request for MUP.

I forked kadirahq/mup and merged @abernix’s pull request for image port and I also merged another pull request that gives unique env variable per server. It is working now with abernix/spaceglue. Here it is:

To build mup you need npm3 or install missing dependencies:

npm install --save-dev npm install nofat babel-cli babel-preset-es2015 babel-preset-stage-3

@jamesgibson14 glad to hear the patches pass.

(I made a longer announcement in another thread, crossposting since it’s relevant here, too. See the announcement for details.)

I made a project called MiniMeteor, which is an easy solution to dockerize Meteor apps, images are as small as 20MB (compressed), supports Docker Hub, doesn’t run as root, works with all versions of Meteor 1.3 and above: https://github.com/aedm/minimeteor