Self-contained Dockerfile for deploying Meteor apps

Hi everyone,

I wanted to share with you all a Dockerfile that I put together over the weekend. I’m calling it “self-contained” because it doesn’t depend on the existence (or maintenance) of any Docker images besides ubuntu node and node:alpine. It’s a multistage Dockerfile, meaning that the final image is a lean, mean Alpine Linux image with your built server code, runtime dependencies, and nothing else.

It borrows heavily from Docker images made by @kaufmae (pozylon/meteor-docker-auto) and @GeoffreyBooth (geoffreybooth/meteor-base), so many thanks to them (and the rest of the community as well) for sharing their work.

It’s up on Github: banjerluke/meteor-dockerfile

Hope you find it useful, and feel free to suggest improvements or point out where I’ve gone wrong. I’m not very experienced with Docker although I’ve learned a lot through the process of getting this to work!

5 Likes

Hi, thanks for sharing. I tried it and ended up with an undefined directory.

The memory consumption is quite massive. Do you know if there is a way to reduce it?

app_1    | files directory: undefined/files
app_1    | creating files directory
app_1    | /opt/app/bundle/programs/server/node_modules/fibers/future.js:280
app_1    | 						throw(ex);
app_1    | 						^
app_1    |
app_1    | Error: ENOENT: no such file or directory, mkdir 'undefined/files'
app_1    |     at Object.fs.mkdirSync (fs.js:885:18)
app_1    |     at files.js (imports/startup/server/files.js:14:6)
app_1    |     at fileEvaluate (packages/modules-runtime.js:343:9)
app_1    |     at require (packages/modules-runtime.js:238:16)
app_1    |     at index.js (imports/startup/server/index.js:1:254)
app_1    |     at fileEvaluate (packages/modules-runtime.js:343:9)
app_1    |     at require (packages/modules-runtime.js:238:16)
app_1    |     at main.js (server/main.js:1:14)
app_1    |     at fileEvaluate (packages/modules-runtime.js:343:9)
app_1    |     at require (packages/modules-runtime.js:238:16)
app_1    |     at /opt/app/bundle/programs/server/app/app.js:1499:1
app_1    |     at /opt/app/bundle/programs/server/boot.js:411:36
app_1    |     at Array.forEach (<anonymous>)
app_1    |     at /opt/app/bundle/programs/server/boot.js:220:19
app_1    |     at /opt/app/bundle/programs/server/boot.js:471:5
app_1    |     at Function.run (/opt/app/bundle/programs/server/profile.js:510:12)
app_1    |     at /opt/app/bundle/programs/server/boot.js:470:11
mongo_1  | 2019-02-21T09:15:13.444+0000 I NETWORK  [conn1] end connection 172.18.0.3:51928 (0 connections now open)
unboxing-server_app_1 exited with code 1

I haven’t experienced any Meteor errors with this setup. I’m not sure but I think it might have something to do with line 14 of your imports/startup/server/files.js. What’s happening on that line in your code?

As for memory usage, I’m not sure what’s causing it. I had assumed that it was mostly the Meteor app being built, but when I build the app on Windows I see that it only uses around 1 GB of RAM, not 2+. Not sure where the other memory usage is coming from.

I switched to Google Cloud Build which made memory issues no longer a worry. Hard to beat 120 free build minutes a day, too! The issue I wrestled with for a long time there was the default 10 minute build timeout; I finally figured out the cloudbuild.yaml setting that would increase that timeout, and added an example cloudbuild.yaml to the repo in case anyone else finds it useful.

I also swapped out the Ubuntu base image in the builder for a smaller Node image which may possibly reduce memory usage, and I did a bit of refactoring of the Dockerfile to reduce the number of intermediate containers.