Dockerizing Meteor (Part II)

I thought it would be simple to dockerize meteor by creating a simple Dockerfile that installed meteor via the standard curl script – as below (full details here: https://github.com/richburdon/docker-meteor)

> FROM ubuntu:trusty
> RUN apt-get update
> ...
> RUN curl https://install.meteor.com | sh
> ...
> CMD ["meteor"]

But when the image runs in the Docker container there are errors with no obvious cause (below). Anybody guess at what is happening, or why the meteor script might not run inside the container?

> => Started proxy.
> => Started MongoDB.

> /root/.meteor/packages/meteor-tool/.1.1.3.4sddkj++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/lib/node_modules/fibers/future.js:245
> 						throw(ex);
> 						      ^
> Error: EXDEV, rename '/home/demo/app/.meteor/local/build'
>     at Object.Future.wait (/root/.meteor/packages/meteor-tool/.1.1.3.4sddkj++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/lib/node_modules/fibers/future.js:398:15)
>     at Object.wrapper [as rename] (/root/.meteor/packages/meteor-tool/.1.1.3.4sddkj++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/tools/files.js:1350:24)

Maybe try https://github.com/meteorhacks/meteord?

@sanjo
I share @richburdon’s frustration, there is no reason it should require the complexity that @arunoda had to deal with in meteord. I personally have not had success with meteord.

Docker is mainstream now. MDG should provide a reference dockerfile for production images. (I’m guessing they never will because it would conflict with the Galaxy business.)

4 Likes

Are you using WORKDIR before the CMD on your Dockerfile? Also you are using this container for development case, right? Because for production using the bundle version of your app is better, so need be like as NodeJS app.

If you want to try/or dev mode using Docker-Compose is the best way.

Your Awesome App folder:

my-awesome-app
  - app //Meteor app here
  - Dockerfile //For use with Docker Compose, dev mode.
  - docker-sompose.yml 

Dockerfile:

FROM ubuntu:trusty
RUN apt-get install curl -y
RUN curl https://install.meteor.com/ | sh

docker-compose.yml:

app:
  build: .
  command: meteor
  working_dir: /home/app
  ports:
    - "3000:3000"
  volumes:
    - app/:/home/app

Inside main folder run: docker-compose up, it will build and run this container and mount the app folder on container, open “http://localhot:3000”.

With Docker-Compose you can have others containers linked for your app. I use that with Cloud9 IDE to work on Chromebook, but I prefer local dev and Docker for production, my problem now is get a tiny Image of Meteor to run in production, but Meteor is not yet compatible with Node 0.12 (error to compile “node-fibers”, need be in ubuntu or more complete OS, not work with Alpine or BuildrootFS) but this is another topic.

@jadsonlourenco You say having a bundle is better for production. Are there any examples of dockerfiles that will automate creating the bundle?

@lpgeiger yes!

First save your app as bundle:

meteor build ../build --architecture os.linux.x86_64

My meteor app are in a folder named “app”, so the bundle file will be with this name “app.tar.gz”, on build folder.

Dockerfile:

FROM ubuntu:trusty

# Install NodeJS from Node-Source repo (node 0.10).
RUN apt-get update && apt-get install -y curl
RUN curl -sL https://deb.nodesource.com/setup | bash -
RUN apt-get install -y nodejs

# Add your app on /Home and install NPM modules. And clean the cache.
RUN mkdir /home/app
ADD app.tar.gz /tmp
RUN mv /tmp/bundle /home/app
RUN cd /home/app/programs/server && npm install
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Expose port 80, but remember to use PORT=80
EXPOSE 80

# Run the app
WORKDIR /home/app
CMD ["node", "main.js"]

This container is for run just the Meteor app, not database and I not recommend to use database on Docker for production, also remember to set the env: PORT, ROOT_URL and MONGO_URL, I use is out of container, following the “12 factors” rules.

I hope get better images soon, with tiny size, like Alpine Linux, but Meteor need the “node-fibers” and it not compile on all Linux OS, and is not compatible with Nodejs 0.12 yet.

Thanks @jadsonlourenco for the response.

My Dockerfile is here: https://github.com/richburdon/docker-meteor/blob/master/Dockerfile (and yes, I am setting the WORKDIR).

So far, I am just trying to get a simple app to run on docker on my Cloud service (Digital Ocean); if I can get that far, then I will look into bundling my app’s for production.

I have the same directory structure and a similar Dockerfile format as you are suggesting, but I still get the runtime error from the previous message.

I tried your docker-compse example also, but it fails with another runtime error (below):

$ docker-compose up

Traceback (most recent call last):
  File "/usr/local/Cellar/fig/1.3.1/libexec/bin/docker-compose", line 9, in <module>
    load_entry_point('docker-compose==1.3.1', 'console_scripts', 'docker-compose')()
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/cli/main.py", line 31, in main
    command.sys_dispatch()
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/cli/docopt_command.py", line 21, in sys_dispatch
    self.dispatch(sys.argv[1:], None)
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/cli/command.py", line 34, in dispatch
    super(Command, self).dispatch(*args, **kwargs)
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/cli/docopt_command.py", line 24, in dispatch
    self.perform_command(*self.parse(argv, global_options))
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/cli/command.py", line 64, in perform_command
    verbose=options.get('--verbose'))
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/cli/command.py", line 83, in get_project
    config.load(config_path),
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/config.py", line 68, in load
    return from_dictionary(load_yaml(filename), working_dir=working_dir, filename=filename)
  File "/usr/local/Cellar/fig/1.3.1/libexec/lib/python2.7/site-packages/compose/config.py", line 74, in from_dictionary
    for service_name, service_dict in list(dictionary.items()):
AttributeError: 'NoneType' object has no attribute 'items'

@richburdon for production test use the other example that I show in last reply, you can use with docker-compose too. Its mean, use Meteor bundle, not dev version. In this case not need mount the “volume”, just open the port in docker-compose.yml

app:
  build: .
  ports:
    - "3000:80"

What your OS, Meteor version, etc. I use that in Ubuntu 14.04 (DO) and in OSX (10.11) and works fine.

Thanks again @jadsonlourenco

I appreciate the suggestion, but I’m still trying to get the dev version to work.

Your production example brings in other dependencies (e.g., node) and requires that I have other docker images to install Mongo. Isn’t the meteor.sh script supposed to hide all of that?

Anyway, I tried both, but “docker-compose up” fails with the same error; it doesn’t seem very mature at this point (I installed it via brew update docker-compose on OS/X).

AttributeError: ‘NoneType’ object has no attribute ‘items’

@jadsonlourenco Thanks for the reply you’ve been very helpful. I’m running into random issues with docker-compose. Seems like I’m having failures at every step of the toolchain. Are there other options without docker-compose? I’m going to private message you next.

OK, after talk with @lpgeiger (private) I understand better your @richburdon use case.
The author want an easy way to deploy the Meteor app on Docker, using a Dockerfile/Image. So, I hope this help: https://github.com/jadsonlourenco/docker-meteor


But for all new Meteor dev: to deploy your Meteor app for web the ideal is to use bundle version (like NodeJS app), Meteor CLI do that, inside your app folder run:

meteor build . --architecture os.linux.x86_64

This command will generate a compressed file of your app, that is a NodeJS app.

For deploying your app you can also use mupx. It’s very straight forward. And it also uses Docker internally. But you don’t have to deal with that.
I suggest to wait for Galaxy and not deal with Docker if you don’t have good reasons (e.g. you already have a production app with a lot of users).

1 Like

Thanks @sanjo. I’m very deliberately not wanting to hide Docker since this is just a small part of a much more complex system, and it’s unsuitable for Galaxy. Just wanting Meteor to play nice with Docker, but it seems there are lots of complications.

@jadsonlourenco thanks again for your very generous responses.

I can now build and run my demo app, but still some problems:

First, on run I get the following error:

Error: Must pass options.rootUrl or set ROOT_URL in the server environment

I really don’t know why this is required (since it is specified in the docker-compose.yml although I don’t understand this either), but I guessed the following:

docker build -t demo .
docker run -P -e "ROOT_URL=http://localhost:3000" -t demo --name demo

So, I can see the process running via “docker ps”:

CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                     NAMES
7e455507f097        demo                "node main.js"      About a minute ago   Up About a minute   0.0.0.0:32771->3000/tcp   demo   

And I can get the host IP (from my local VirtualBox – managed by boot2docker on OS/X)

boot2docker ip
192.168.59.103

But the server doesn’t respond with the demo app:

curl 192.168.59.103:32771
curl: (7) Failed to connect to 192.168.59.103 port 32771: Connection refused

(And the same error if I ssh onto the VirtualBox and run “curl localhost:32771”).

Also, “docker logs 7e455507f097” shows an empty log.

Can you think of another way to check if the node app is running – or why it may have failed silently?

Thanks!

OK have docker-compose working now (i.e., “docker-compose up”); I don’t know what was wrong before.

Thanks.

1 Like

@richburdon I think the error to recognise the environment variables was because of the cache, so the ideal is to run the Docker on a Linux Host (like a VM, with vagrant or Boot2Docker it’s easy). But I am glad that you get it solved.
I got a new image, tiny and good for production, that has nothing, just the things necessary to run the app: NodeJS+NPM. But it is not yet ready because I can’t “revolve” the DNS, its mean to connect to the database need to use an IP, but I will release and even show the advantages of using Docker. Any way I’m happy to help, thanks.

I just wrote a tutorial on how to deploy a meteor app to Amazons Elastic Container Service. The forum post is here: Docker, Meteor, and AWS ECS

And the tutorial post is here: http://krishamoud.me/deploying-meteor-to-aws-ecs/

1 Like