Reputation: 835
I'm trying to containerize a Node application that creates snapshots of .STL files. This application is started through xvfb-run
to provide it a mock GUI in which it can generate said snapshots, and it works if I just run the application without a container, but when I try to containerize it, xvfb-run
simply hangs. Nothing is printed in the container console, there are no logs, and adding -e /dev/stdout
to xvfb-run
doesn't output anything.
This is my dockerfile:
FROM debian:latest AS build-env
WORKDIR /app
COPY src ./src
COPY tsconfig.json ./
COPY package.json ./
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -my wget gnupg
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash
RUN apt-get install -y nodejs build-essential libxi-dev xvfb libgl1-mesa-dev libglu1-mesa-dev libglew-dev
RUN npm install .
RUN npm install -g typescript
RUN tsc
EXPOSE 3000
CMD ["xvfb-run", "node", "dist/examples/server.js"]
Example run (the cursor hangs there forever, nothing is ever printed)
Edit: Just wanted to clarify that it IS supposed to print something - the Express server prints something when it starts, so I can tell it's not starting and something is wrong. I can also confirm that the xvfb-run
command is present, as running it without any other arguments displays a help message.
Upvotes: 10
Views: 3211
Reputation: 643
maybe late, but just saw your post. You probably need something like tini, so use --init flag when you do docker run
. This will load init system as the ENTRYPOINT
Wine is a good example about how to use it
And to use it in docker-compose, just add init: true
(inside the service).
I also found something similar, maybe it's useful for you too: stl-thumb
Hope it helps!
Containers are designed to run a single primary process. However, when running complex applications or scripts like xvfb-run
, which might spawn child processes, managing these processes can become challenging. In a standard Linux environment, the init
system (like systemd
or SysVinit
) is responsible for process management. In containers, this system isn't present by default.
Without an init
system, terminated child processes might become zombie processes. These are processes that have completed execution but still have an entry in the process table. This occurs because the parent process has not read the status of its terminated child process. Over time, these zombie processes can accumulate, consuming system resources.
Tini (--init
or init: true
) acts as a minimal init system. It's a tiny utility that handles the reaping of zombie processes and performs signal forwarding. By using --init
in docker run or setting init: true
in Docker Compose, Tini is automatically added to your container and set as the entrypoint. This means it will handle process management, ensuring that when child processes exit, they don't turn into zombie processes.
As best practice, with Docker we should keep containers as simple as possible. However, when multi-process management is necessary, tools like Tini become essential for proper operation and resource management. 😉
Upvotes: 21