13

My team is currently trying to decide if we should deploy our Nodejs app as a deb package instead of trying to run it in a container such as Docker.

I got this idea from reading this blog here which makes some good arguments for using a deb package for a pre-existing python application. The main point from this blog which is appealing to us is the issue of maintaining the Docker ecosystem (port sharing, permissions, hosting of Docker Images, etc.)

It seems like "dep-packages as the original containers" makes a lot of sense for small services where there is no concern of port conflicts and where all the dependencies are maintained within a virtual environment.

My gut, however, is telling me that if deb packages were a good fit, it would be more common and docker would be advertised as a more language specific solution. Are there any drawbacks of using something like deb packages to deploy our services, instead of using a full system such as docker?

  • 1
    Those aren't mutually exclusive, you could deploy your deb package in a Docker container. Maybe you should be asking about Microservices vs Virtual Machines? – Chris Feb 28 '17 at 17:38
  • Hmm, no this is specifically about using a deb-package instead of docker container. I'll add more information from the blog into the question. – avi Feb 28 '17 at 17:40
  • 3
    "we felt that upgrading the kernel just to ship code faster was an overkill solution." this just sounds wrong to me. what could be more important than shipping code faster? – Assaf Lavie Feb 28 '17 at 17:53
14

First, while Docker is sometimes seen and used as a ad hoc packaging system, it actually solves a totally different problem: Docker is about running programs. The Docker system allows to describe services, that can be scaled at will and to control swarms of containers. Debian packages are for installing programs and they are able to handle dependencies between software versions. Docker certainly don't qualify as a descent packaging system: each “package” can only have one dependency, the system has no “recursive build” option and does not support complex version constraints!

A possible answer would be that, if you are willing to write a Debian package for your application, you can also use Docker to deploy your application. This can be achieved with a configuration script apt_setup.sh which would look like

apt-key add - <<EOF
-----BEGIN PGP PUBLIC KEY BLOCK-----
<YOUR RELEASE OFFICER PGP KEY GOES HERE>
EOF

cat >> /etc/apt/sources.list <<EOF
deb https://my.organisation.org/repo debian-jessie main
apt-get update -y
apt-get upgrade -y
EOF

and a Dockerfile along the lines of

ADD apt_setup.sh /root
RUN sh -ex /root/apt_setup.sh && rm /root/apt_setup.sh
RUN apt-get install -y my-node-js-package

(In your specific situation, the apt_setup.sh would be more complicated, adding the nodesource repositories and some helper packages such as apt-transport-https.)

It is therefore really possible to use Debian packages and Docker simultaneously, however …

My gut […] is telling me that if deb packages were a good fit, it would be more common

This is a correct hitch which leads us to ask ourselves why Docker proves to be popular as a ad hoc packaging system, while it is not intended to be one. (See above.)

The “official” packaging system from a given distribution is just a possibility among many others to install software in some computing environment. There are many other sources available, like community-specific package managers such as npm or opam, port trees like pkgsrc and plain source code distribution. From this perspective, it is easy to understand the success of Docker as an ad hoc packaging system:

  • Docker specifications are very close from a shell script and whatever source it comes from, we install software using the shell.

  • Docker has a “built-in” (paying) service for hosting artefacts it produces, the Docker Hub.

Now what are the strength of Debian packages over Docker images as a package system? The tight control over dependencies at installation. (The possibility to upgrade and downgrade also exists but has no practical importance if we are implementing the pattern.) This leads to the

Conclusion

If you only have a single product deployed in a single version (which is typical for SaaS), your version management needs are very simple and using Docker as a ad hoc package manager should not have any hard drawbacks. As soon as you work with several versions of a single product or several products, the complexity of the version constraints problem you need to solve increases and you need an appropriate tool for this, which might be Debian packages or some configuration management system if you are mixing software from different origins.

5

A Debian (or RedHat) package to install applications has been a good practice when done correctly. Packages are used for the purpose of deploying applications which are infrequently changed. Debian packages involve some overhead, like version management, dependency management, pre&post-install scripts, etc...

In many cases upgrading from some older version to a new version requires the careful writing of scripts, attention to details in version, etc. Because mutating existing state is difficult. It would be much easier to replace the current state altogether with a new state, without mutating anything.

Once you decide to completely replace your configuration or dependencies or application on each deployment because it is easier and less error prone. Most organizations (used to) switch to a whole new VM or cloud instance. Which means that installing the package would be done on a "clean" server, and mutating the files and configuration on the server is not a problem anymore.

Those developers who created packages and did not understand the fallacy and complexity in mutations suffered quite a lot of difficulties as a result.

Replacing VMs is sub-optimal when all you need is to replace an application, which is why lightweight containers were introduced as an answer. Using Docker (or other LWC) you can replace the userbase, including all the dependencies, without replacing the server itself. You can also host multiple versions of the same application, with different dependencies, on the same server and only switch the incoming network traffic on upgrade. As well as switch network traffic back on rollback (blue-green), something that was remarkably hard in the case of managing deployments via packages.

Containers introduce a way to bundle all the application code, and dependencies, and configuration, into an image. This image has multiple properties that make it much better than traditional operating system packages. For example, it has tags that enable versioning, but it also has layers, which enable to save on space. It allows an easy way to ship these images to servers, and development environments, by using a registry. And these images can be executed as containers in any environment and any server, almost identically. This includes the developer's laptop as well as the production environment. Again, something that was much more difficult to do with VMs and/or with package-based versions of the software. Having the same image tested on the developer's laptop, and staying the same bits and bytes in production removes a lot of "works on my machine" problems.

  • So far I'm finding it replaces "works on my machine" with "works on my machine, but behaves bizarrely in Docker". – Matt Moran May 11 '17 at 7:50
4

Yes, there's drawbacks.

With a .deb package you won't be able to have two version of the same application on the same host. You will have to rely on the distribution available packages, if your app rely on nodejs for example, either you'll be stuck with the distribution version or you'll have to install your own.

Now when you want to host multiples applications on the same host, you'll be hitting a wall very quickly when they depend on the same thing (let's keep nodejs here) in two different versions.

The main goal of docker is to isolate each application from the hosting system and others applications on the same host. there's two reason to do this isolation: 1. to avoid compromission of the app to be able to take over the host or impact another application 2. to give the application its exact dependencies and prevent it to be impacted by a system update or another application dependency.

  • Uh, no one suggested using the distribution's ruby, node, python, etc. You make packages of those as well and put them in /opt. Your packages will depend on these. You can absolutely have multiple versions of your app installed with deb packages, there are many examples in Debian itself. In fact, it is the best way to manage multiple versions. This answer is completely wrong. – figtrap Mar 12 '18 at 19:29
  • @figtrap OK try to use official elastic.co repo and install elasticsearch v. 2.3 and v. 5.6 concurrently. What you're describing is installing two different packages and heavy tweaking if you're doing proper .deb packages. That's a nightmare in term of build dependencies as well as maintenance when you need two different versions of libc somewhere deep in the stack. – Tensibai Mar 12 '18 at 21:39
1

Talking specifically about the image packaging piece of Docker, not the container runtime there are a few minor bits. The biggest is that a Docker image is more like a chroot, which means you are prevented from accidentally depending on shared system state since every file in use must be explicitly included in the image while a system package might pick up dynamic links you didn't expect or otherwise get more intertwined with other packages. This can come up with complex C dependencies getting loaded without your knowledge, for example OpenSSL. Additionally using deb packages don't de-duplicate shared bits in the say Docker's storage system does. For some this might be a good thing, better I/O performance and fewer moving pieces, but for others it might be a problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.