franz-josef-kaiser / Docker-Alpine-Nodejs

Highly configurable Docker Nodejs container

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nodejs dockerized on Alpine OS

Build Status Stories in Ready

Builds a small and highly versatile Docker container, running Alpine Linux OS latest version and Nodejs on top. Optional installation of npm and, depending on that, installs packages on demand.

Configuration

There are various parts that you can define when building your image:

docker build -t nodejs:custom 

ENV variables:

  • VERSION - The Nodejs version number; Default: 5.6.0
  • NPM - Set to "yes" (or whatever) if you want to install npm as well; Default: yes
  • NPM_VERSION - Define the npm version you want to install; Default: 3.6.0
  • NPM_NPM_CONFIG_LOGLEVEL - Define the npm log level for dev installs. For e.g. info. Default: warn
  • PREFIX - The --prefix for installing Nodejs and npm; Default: /usr
  • FLAGS - Any additional flags you want to pass to the configure call when building Nodejs; Default: none, but due to a bug, --fully-static will be removed even if set.
  • TARGET - The installation target, prefixed by PREFIX, so please leave that off; Default: ${PREFIX}/lib/app
  • SRC - From where to fetch the original files for the ONBUILD commands; Default: ./app; Note will probably get removed
  • ADDT_PACKAGES - Additional (permanent) packages from the Alpine OS package repository, set for e.g. wget or nano here; Default: none

As Nodejs was not designed to run with PID 1, this image uses tini as process reaper.

All Tini does is spawn a single child (Tini is meant to be run in a container), and wait for it to exit all the while reaping zombies and performing signal forwarding.

How To

Images are highly versatile and can be customized, using above env variables. Build the image on the command line (assuming the Dockerfile is in a subfolder):

docker build -t nodejs:latest ./Docker/Nodejs/

Per default, the container comes without npm. To install with NPM and adjust both the Node and NPM version, you have to use the --build-arg flag:

docker build -t nodejs:5.6.0 --build-arg VERSION="5.6.0" NPM_VERSION="3" NPM="yes" ./Docker/Nodejs/

Development builds should be done without cache:

docker build --no-cache -t nodejs:dev ./Docker/Nodejs/

Docker Compose

Docker Compose Example:

version: '2'

services:
    nodejs:
        container_name: nodejs
        build:
            context: ./Docker/Nodejs
            args:
                VERSION: "5.6.0"
                NPM_VERSION: "3"
                NPM: "yes"
                PREFIX: "/usr"
                TARGET: "/src/app"
                SRC: "./app/node"
        restart: on-failure:3
        expose:
            - "3000"
        depends_on:
            - app
        volumes_from:
            - app
        command: [ "node", "server.js" ]
        #command: npm install --force --loglevel=error
        networks:
            - front

    app:
        container_name: app
        image: busybox:latest
        volumes:
            - ./app/node:/usr/src/app
        networks:
            - front

volumes:
	eapp:

networks:
    front:
        driver: bridge

You can then check your attached volume:

$ docker volume ls
local    projectname_app

In case you need to remove your volume container:

docker volume rm $(docker volume ls |awk '{print $2}')

Details about the volume are then available via:

docker volume inspect <volume_name>

# Example:
$ docker volume inspect projectname_app

[
    {
        "Name"       : "projectname_app",
        "Driver"     : "local",
        "Mountpoint" : "/mnt/sda1/var/lib/docker/volumes/projectname_app/_data"
    }
]

Sidenote: You might want to docker-compose down your Nodejs service to get a fresh start before going to create volumes.

FAQ

Q: What is the license?

A: MIT License (Expat). tl;dr: Basically, you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. tl;dr. See the attached license file in this repository for the full text.

Q: The GPG verification fails with gpg: no ultimately trusted keys found. Why that?

A: The only key that you can trust is your own. You can sign other peoples keys as "trusted", something that you only want to do if you know them in person and really trust them. If you have such a person and this person knows someone who knows someone who knows the person who signed that release, then you can build a "chain of trust" and absolutely verify a key. For every real world use case, above verification is more than enough. And key signing never hit a critical mass to build a web of trust easily. In other words: The message is a bit misleading.

Q: The GPG verification states gpg: WARNING: not a detached signature;. Why that?

A: The signature asc file checked out good, but warned about it not being certified with a trusted signature. As learned in the previous step, it just tells you that you did not sign it yourself.

Q: I get gyp: true not found (cwd: /node-v5.6.0) while trying to load true. Error running GYP when trying to build the image.

A: You should define all build arguments as strings. Do not set --build-arg NPM=true, but use --build-arg NPM="true" (or better: yes) instead to avoid using a real boolen. The same has to be done when using Docker Compose. Set build: args: NPM: "yes" as string.

Tests

Currently there are acceptance tests shipped with this package. The specs are run using Ruby and the following Gems:

To run tests, you need Ruby and the listed Gems installed. The test can be run on the command line:

$ Print progress bar/dots while running tests
$ rspec --format progress Dockspec.rb
# Short notation
$ rspec -f p Dockspec.rb
# Verbose output (Print spec titles) while running tests
$ rspec --format documentation Dockspec.rb
# Short notation
$ rspec -f d Dockspec.rb

The docker-api Gem will remote execute Docker, which means that the test run is a real world test and will fully expose things that might go wrong.

macOS users can run the tests inside the terminal when they have the docker status bar app installed (running Hypervisor) Windows and older OS X users will have to run the tests inside their Docker Machine.

Security

OS Alpine Linux has a very small foot print and therefore only a tiny attack surface. In addition, it features SELinux for enhanced security. Still it is recommended to have a firewall, proxy or load balancer in front of your Node servers to not expose them directly to the public.

Packages The download gets verified using GNU Privacy Guard/gpg. That means that if the source repo should get compromised, the build will fail with the following message:

node-v5.6.0.tar.gz: FAILED
sha256sum: WARNING: 1 of 1 computed checksums did NOT match

The repo itself comes with a prepackaged public keyring, containing all current and previous contributors. The validity and integrity of the Nodejs download will be verified using this trust database. This is to work around unreliable key servers. If you want to take a look at the keys, check the Dockerfile, where you will find a GPG_KEYS env variable containing them all.

TO-DO

The build is currently not running smoothly. There are some things that need fixing. If you can help, please open an issue, to discuss any idea you have in mind. If that results in a pull request, I am happy to give you AAA-access to this repo. Please take a quick look at CONTRIBUTING - you will not find any surprises there.

  • Nodejs probably shouldn't run as root on this machine. When everything works as root, there should be a non privileged node user in place. See uncommented parts of the Dockerfile.
  • Maybe there should be an ENTRYPOINT in place to pass commands directly to npm and avoid fiddling with node.
  • The file removal after the installation of NPM could be much easier and just set a whitelist. That would also mean that it's more versatile regarding the folder structure of various versions. Also we need to check the folder structure first and maybe switch the whitelist depending on the version.

About

Highly configurable Docker Nodejs container

License:MIT License


Languages

Language:Ruby 95.8%Language:Shell 4.2%