Deploy Meteor with Docker

Install Docker

$ sudo apt-get update
$ sudo apt-get install docker.io

Install MongoDB on the target server

$ sudo docker pull horka/mongodb
$ sudo docker run -p 27017:27017 --name mongo_instance -d horka/mongodb

Dockerfile for your Meteor app

# deploy/Dockerfile
# Dockerfile for your app.
# Change "budgeter" in the Dockerfile to your app's name
FROM node:0.10MAINTAINER Levente Balogh <balogh.levente.hu@gmail.com>RUN apt-get install -y curl
RUN curl https://install.meteor.com/ | /bin/sh
# Change "budgeter" to your app's name
ADD . /opt/budgeter/app
# Install NPM packages
WORKDIR /opt/budgeter/app/programs/server
RUN npm install
# Set environment variables
WORKDIR /opt/budgeter/app
ENV PORT 80
ENV ROOT_URL http://127.0.0.1
ENV MONGO_URL mongodb://mongo_instance:27017/budgeter
# Expose port 80
EXPOSE 80
# Start the app
CMD node ./main.js

Add a Makefile to your project

# Makefile
# Replace <app-name> with your app's name
# Replace <server-ip> with your server's IP address
# Replace <image-name> with custom docker tag.
# (<username>/<appname>) format
# Replace <container-name> with a custom name.
APP_NAME:=<app-name>
TARGET_DIRECTORY:=<target-directory>
SERVER_IP:=<server-ip>
IMAGE_NAME:=<image-name>
CONTAINER_NAME:=<container-name>
TARBALL_NAME:=bundle.tar.gz.
URL:=<url>
PORT:=<port>
PHONY: build
build:
@echo "-------------------------------------------------------"
@echo "Creates a tarball under ./deploy"
@echo "-------------------------------------------------------"
@echo "Building..."
# Remove previous build
@rm -rf ./bundle ./deploy/$(TARBALL_NAME)
@meteor build . --server="$(URL)" --directory
@cp ./deploy/Dockerfile ./bundle
@tar -zcf ./$(TARBALL_NAME) ./bundle
@mv ./$(TARBALL_NAME) ./deploy
@rm -rf ./bundle
@echo "Builded successfully!"
@echo "(the build output tarball is ./deploy/bundle.tar.gz)".
PHONY: deploy
deploy:
@echo "-------------------------------------------------------"
@echo "Uploading and running app in a docker container"
@echo "-------------------------------------------------------"
@ssh root@$(SERVER_IP) \
"cat > $(TARGET_DIRECTORY)/$(TARBALL_NAME) ; \
cd $(TARGET_DIRECTORY) ; \
tar -xzf ./$(TARBALL_NAME) ; \
cd ./bundle ; \
docker stop $(CONTAINER_NAME) ; \
docker rm $(CONTAINER_NAME) ; \
docker build --tag $(IMAGE_NAME) . ; \
docker run -p $(PORT):80 --name $(CONTAINER_NAME) -d $(IMAGE_NAME) ; \
" \
< ./deploy/$(TARBALL_NAME)

Usage

$ make build
$ make deploy

View in browser

Multiple applications on one server

sudo apt-get update
sudo apt-get install nginx
sudo nano /etc/nginx/sites-available/budgeter.xyz
# /etc/nginx/sites-available/budgetermap $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

# root is irrelevant
root /usr/share/nginx/html;
index index.html index.htm;
server_name budgeter.xyz;location / {
proxy_pass http://127.0.0.1:8085;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr;
if ($uri != '/') {
expires 30d;
}
}
}
sudo ln -s /etc/nginx/sites-available/budgeter.xyz /etc/nginx/sites-enabled/budgeter.xyz
sudo service nginx restart

--

--

--

I think one of the most important thing in our life is curiosity. Stay curious, understand truly how things work and become a master craftsman. This is my goal.

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Levente Balogh

Levente Balogh

I think one of the most important thing in our life is curiosity. Stay curious, understand truly how things work and become a master craftsman. This is my goal.

More from Medium

OAuth 2.0 with Passport.js Part — 2

Using DotEnv Config Files in TypeScript

Integrate AWS GraphQL in your Ionic/Angular applications using Amplify.

Websocket Connection Using Shared Worker