A common migration pattern when moving to docker includes running some systems (e.g. dev, staging or a prod canary) on your docker image while the production app is still running your traditional tgz artifacts (e.g. your node app with node_modules)

Let’s create a travis build that creates two artifacts: (1) your docker image and (2) a tgz from the docker container.

Let’s assume you have a basic dockerfile with your app.js and a package.json. The key is that the app is built into /usr/src/app

FROM node:4

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.20.3
ENV PATH=/root/.yarn/bin:$PATH
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
COPY yarn.lock package.json /usr/src/app/
RUN env
RUN yarn install --production

# the app will be installed here
# we'll use docker cp later to generate the tarball
COPY . /usr/src/app
CMD [ "yarn", "start" ]
EXPOSE 9000

On travis, or your personal build server, use the following steps to create the TGZ from your docker image

- # build your docker image
- docker build -t node-app:${TRAVIS_BUILD_NUMBER} .
- # create a container-- don't run it
- container_id=$(docker create node-app:${TRAVIS_BUILD_NUMBER})
- # docker cp tar's to STDOUT -- gzip that and save to your tar.gz
- docker cp $container_id:/usr/src/app/.  - |  gzip -c > release/node-app-${TRAVIS_BUILD_NUMBER}-from-docker.tar.gz

Gotchyas

Make sure your docker base image OS and your target tgz OS are the same. e.g. if you’re using debian/jessie for your VMs, your base docker images should be the same. This way linked binaries will be compatible within and outside your image.