Saturday, April 1, 2017

Configuring your own docker image for Meteor app deployment

This blog assumes a post 1.4 Meteor app, and its cloud deployment using the mup tool (Please see  this for npm download and find the code on https://github.com/zodern/meteor-up). Also see this for deployment on Digital Ocean using mup, although it is a bit dated. For example mup.json file has changed to mup.js and some of the json structure in there also differs.

The way that mup loosely works is that it compiles and tar-zips your application code, uploads it over to/opt/onlinetesting1/tmp on your cloud machine in addition to the docker run script to be run. On the cloud VM, the script (built by mup from mup.js) when run takes as an installation base, the docker image abernix/meteord (settable in mup.js) by pulling it from docker hub (e.g. download using 'docker pull abernix/meteord' command if you have docker installed on your machine, to get a feel), and finally runs the docker image with a volume mapping from /opt/onlinetesting1/tmp on the host machine ( your cloud VM) to /bundle in the docker container, and also passing various docker container environment settings for mongodb MONGO_URL and port, application server port, application name, meteor ROOT_URL etc.. The docker image 'entry point' was itself configured a priori (by the author of abernix/meteord) to run the meteor app server start up script when a container is created and run from the image. The docker run script is uploaded by mup to /opt/onlinetesting1/config/ on the host VM.

mup has a single point method of specifying the above settings as also all settings for the tool to log into the cloud VM using ssh. That single point is the mup.js file. Please see this for details. Please refer to  this to know how ssh login to your cloud VM works using an ssh-keygen authored digital certificate from your machine.

As happens very often, the above procedure didn't work OOTB for me. The docker image abernix/meteord comes with node 4.x and phantomjs 1.9.x preinstalled. But our meteor app for Online testing had problems with phantomjs 1.9.8.
 You may ask why we couldn't take the route of simply installing our version of phantomjs (2.1.1) into our cloud-installed docker container. The issue here is that even if we saved the container locally back to the image, the latter would get overwritten the next time we did a 'mup deploy' to deploy our new changes.

Here is what worked for me finally - create my own base docker image from abernix/meteord with pantomjs 2.1.1 (and vi editor !) installed. Then upload it to docker hub. Here are the steps :-

Create a folder called anything - 'dockerstuff' may be - somewhere. Then create a file called 'Dockerfile' in that folder. Also create a 'script.sh' file with the following code, in that folder.
#!/bin/bash

while true; do
    read -p "Give a y/n input"  yn

done

Don't forget to change its permissions to 777. Why a script that stops by expecting input ? Because we are going to keep the container alive by tying it with a process that potentially doesn't end. This is because we want to do something useful by opening a bash shell on the container, next, and we can't do that if the container has already finished with its start up script and stopped. There are probably other, even easier ways to do this, but this way works too. For other options see for example, this. Now put the following lines to execute the startup script, 'script.sh' in Dockerfile

FROM abernix/meteord:base
ADD script.sh / 
ENTRYPOINT /script.sh 
The ADD command adds the script.sh from the host into the / (root) folder of the container. The ENTRYPOINT command changes the startup process from the one for which the parent image (abernix/meteord) is configured to our simple one from script.sh.

Now build your image. At the shell prompt type

docker build -t test:base .
This creates a new image with the above entry point, but based otherwise on abernix/meteord.
To see a listing of all docker images, type
docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
test                         base               b30086a9e634        23 seconds ago        645 MB

abernix/meteord              base                edaae2ab7250        2 weeks ago         514 MB
Run the image b30086a9e634  to start a new docker container.
docker run -d  b30086a9e634
Here -d is for starting the container in the background. To see the container id type
docker ps -s
You get a listing like this
CONTAINER ID        IMAGE             COMMAND                  CREATED             STATUS              PORTS                        NAMES               SIZE
fecae970f27b        test:base   "/bin/sh -c /scrip..."   21 seconds ago        Up 21 seconds         0.0.0.0:80->80/tcp           quirky_allen      824 B (virtual 514 MB)

Create an interactive shell in this container

docker exec -it fecae970f27b bash
Now you are in a shell of the container, and as root user !
Remove all old phantomjs links and installations
rm -r /usr/local/bin/phantomjs /usr/bin/phantomjs /usr/local/share/phantomjs /usr/local/share/phantomjs-1.9.8-linux-x86_64
 Install latest phantomjs (it is 2.1.1 as of now)
npm install -g phantomjs-prebuilt
Install whatever else you want. For example, I installed the vi editor.
Exit the shell
exit
 Now you are back to you host machine shell prompt.
First thing, save your changes to the image.
docker commit fecae970f27b test:base
Now create your new image by now specifying test:base as parent in Dockerfile but reverting to the original entry point from abernix/meteord
 FROM test:base 
ENTRYPOINT bash $METEORD_DIR/run_app.sh

Then create the image. Lets call it ssashita/testjha
docker build -t ssashita/testjha:base .
Then check that the ssashita/testjha:base image got created by running
docker images

Now we have an image that has the correct version of phantomjs. We now need to upload this on docker hub so that mup tool can pull it from the cloud VM.
For this I first need to login to my docker account (create one if you don't have one, and follow along on the site and create a public repository. It's easy).
docker login --username=ssashita

Now push the image to your dock hub account
 docker push ssashita/testjha 
 This might take a while to finish.

Next go to your app deploy folder ( mine is .deploy under the app root). Edit the mup.js file.
Change docker.image to "ssashita/testjha:base" (from abernix/meteord:base).

That's it. Follow rest of the instructions in this to complete the cloud deployment. For example you will need a
mup setup
followed by
mup deploy 


No comments:

Post a Comment

Is this stock advise worth taking seriously?

 Introduction Business related TV channels and newspapers are replete with stock advisory from investment firms and certified individua...