Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node and docker - how to handle babel or typescript build?

I have a node application that I want to host in a Docker container, which should be straight forward, as seen in this article:

https://nodejs.org/en/docs/guides/nodejs-docker-webapp/

In my project, however, the sources can not be run directly, they must be compiled from ES6 and/or Typescript. I use gulp to build with babel, browserify and tsify - with different setups for browser and server.

What would be the best workflow for building and automating docker images in this case? Are there any resources on the web that describes such a workflow? Should the Dockerimage do the building after npm install or should I create a shell script to do all this and simply have the Dockerfile pack it all together?

If the Dockerfile should do the build - the image would need to contain all the dev-dependencies, which are not ideal?

Note: I have been able to set up a docker container, and run it - but this required all files to be installed and built beforehand.

like image 652
Jørgen Tvedt Avatar asked May 24 '16 07:05

Jørgen Tvedt


People also ask

Should you use Babel with node?

You should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly.

Why do we need Babel node?

A common reason Babel is frequently involved in the build process for Node webapps is that Babel allows us to easily compile ES6 code to older versions (usually ES5), because it has better browser support. For a purely server-side app, there is no reason, other than maybe slight performance gains, to compile to ES5.

Does Docker use node?

Docker images can be inherited from other images. So instead of creating our own base image, we'll use the official Node. js image that already has all the tools and packages that we need to run a Node.

What is node JS in Docker?

Node. js is a JavaScript framework that is used for developing server-side applications. It is an open source framework that is developed to run on a variety of operating systems. Since Node. js is a popular framework for development, Docker has also ensured it has support for Node.

Does Babel use a dockerfile?

It uses a separate Dockerfile, so you can include both build output and some original files (config files and etc.) I personally prefer to just remove dev dependencies after running babel during build:

Is it possible to use typescript in a dockerfile?

The modern recommendation for this sort of thing (as of Docker 17.05) is to use a multi-stage build. This way you can use all your dev/build dependencies in the one Dockerfile but have the end result optimised and free of unnecessary code. I'm not so familiar with typescript, but here's an example implementation using yarn and babel.

How to use typescript with Babel?

There is one crucial thing regarding typescript with babel - namely, babel only transpiles the files - it does not check types. For types checking you have to use typescript tsc command with .tsconfig.json separately.

How to create a typescript application in Node JS?

Creating every Node.JS application starts with a simple command npm init If you add -y , it will fill all input for you and create a package.json file necessary for managing our application dependencies required for it to run. Since we said we’re going to use TypeScript, we have to set up our project to work with TypeScript right away.


2 Answers

The modern recommendation for this sort of thing (as of Docker 17.05) is to use a multi-stage build. This way you can use all your dev/build dependencies in the one Dockerfile but have the end result optimised and free of unnecessary code.

I'm not so familiar with typescript, but here's an example implementation using yarn and babel. Using this Dockerfile, we can build a development image (with docker build --target development .) for running nodemon, tests etc locally; but with a straight docker build . we get a lean, optimised production image, which runs the app with pm2.

# common base image for development and production FROM node:10.11.0-alpine AS base WORKDIR /app   # dev image contains everything needed for testing, development and building FROM base AS development COPY package.json yarn.lock ./  # first set aside prod dependencies so we can copy in to the prod image RUN yarn install --pure-lockfile --production RUN cp -R node_modules /tmp/node_modules  # install all dependencies and add source code RUN yarn install --pure-lockfile COPY . .   # builder runs unit tests and linter, then builds production code  FROM development as builder RUN yarn lint RUN yarn test:unit --colors RUN yarn babel ./src --out-dir ./dist --copy-files   # release includes bare minimum required to run the app, copied from builder FROM base AS release COPY --from=builder /tmp/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY --from=builder /app/package.json ./ CMD ["yarn", "pm2-runtime", "dist/index.js"] 
like image 163
Greg Avatar answered Sep 17 '22 14:09

Greg


One possible solution is to wrap your build procedure in a special docker image. It is often referred as Builder image. It should contain all your build dependencies: nodejs, npm, gulp, babel, tsc and etc. It encapsulates all your build process, removing the need to install these tools on the host.

First you run the builder image, mounting the source code directory as a volume. The same or a separate volume can be used as output directory. The first image takes your code and runs all build commands.

As a first step you take your built code and pack it into production docker image as you do now.

Here is an example of docker builder image for TypeScript: https://hub.docker.com/r/sandrokeil/typescript/

It is ok to have the same docker builder for several projects as it is typically designed to be general purpose wrapper around some common tools. But it is ok to build your own that describes more complicated procedure.

The good thing about builder image is that your host environment remains unpolluted and you are free to try newer versions of compiler/different tools/change order/do tasks in parallel just by modifing Dockerfile of your builder image. And at any time you can rollback your experiment with build procedure.

like image 36
gerichhome Avatar answered Sep 16 '22 14:09

gerichhome