Custom runtime images
Sometimes the Envoryx image is one package short. Your PDF library wants Ghostscript, a PHP extension isn’t in the list, or the team already has a hardened base image. For that, a runtime can run an image of your own instead of the Envoryx one.
You set it in the project’s Runtime section, on the Runtime images card at the bottom. It has a row for each runtime the project has (PHP, Node.js, Python, Go, Ruby, Java, .NET), and the Image field offers three choices: Envoryx image (the default), Image from a registry and Dockerfile in the project. Databases, the other services and the web server always keep the Envoryx images. Workers and cron jobs run in the image of their runtime, so they follow your choice.
An image from a registry
Section titled “An image from a registry”Put any reference into Image reference, like ghcr.io/acme/php:8.4, and save. Envoryx pulls
it right then, so a tag that moved is picked up, and every Restart pulls it again, just like
the Envoryx images. If the project is running, its containers are recreated with the new image
straight away; otherwise it applies at the next start.
A Dockerfile in the project
Section titled “A Dockerfile in the project”This is the one I’d reach for first, because the Dockerfile lives in the repository next to the
code and the whole team gets the same image. Give the path relative to the project directory; the
field suggests .envoryx/php.Dockerfile (or node, python, … for the other runtimes). Envoryx
builds it and tags the result envoryx-build/<runtime>:<hash>.
Start from the Envoryx image of your version, then you keep everything Envoryx relies on (Composer, Xdebug, mail to Mailpit and so on) and only add what’s missing:
FROM ghcr.io/envoryx/envoryx-php:8.4RUN apt-get update && apt-get install -y --no-install-recommends ghostscript \ && rm -rf /var/lib/apt/lists/*COPY conf/ /usr/local/etc/php/conf.d/The directory of the Dockerfile is the build context, and all of it goes to Docker. That’s why
the Dockerfile wants a directory of its own like .envoryx/ rather than the project root: a
context with more than 5000 files or 512 MB is refused. Symbolic links in it are left out, and
.dockerignore isn’t read. Envoryx builds with Docker’s classic builder, so BuildKit-only syntax
like RUN --mount=… or heredocs won’t work.
The tag’s hash covers the Dockerfile and every file next to it. Change one of them, and the next start or Restart builds a new image; leave them alone, and nothing is built twice. A restart builds before it stops anything, so a broken Dockerfile leaves the running project as it is. A failed build keeps your setting and shows its output under the row, open, with a build failed badge, so you fix the file and try again. Projects with the same context share the image, and a branch environment builds the Dockerfile of its own branch.
Rebuild without cache builds again with freshly pulled base images and without Docker’s build
cache. You need it when nothing in your context changed but the world did: a new Envoryx image
under the same tag, or an apt-get that should fetch newer packages.
The check
Section titled “The check”Envoryx expects a few programs in a runtime image, so it checks every image when you set it and
after every build. It runs the image once with sh -c and looks for:
| Runtime | Needed | Missing means no … |
|---|---|---|
| all | sh |
git (git in the terminal, packages from git repositories), socat (waiting for the database at start, SSH port forwarding), ssh (git over SSH with the deploy key), rsync (rsync over SSH) |
| PHP | php, php-fpm |
composer (Composer installs), msmtp (mail() to Mailpit), the Xdebug extension (step debugging) |
| Node.js | node, npm |
corepack (pnpm and Yarn) |
| Python | python3 (or python) |
pip (pip installs), uv (uv projects) |
| Go | go |
air (live reload), dlv (debugging), gotestsum (test reports) |
| Ruby | ruby, bundle |
rdbg (debugging) |
| Java | java |
mvn, gradle (Maven and Gradle projects without a wrapper) |
| .NET | dotnet |
netcoredbg (debugging), dotnet-ef (EF Core migrations) |
It also looks at the image itself. An ENTRYPOINT other than tini, dumb-init or the official
images’ entrypoints is named, because it runs before every command Envoryx starts and has to end
with exec "$@". A PHP image that isn’t built from the Envoryx PHP image gets told that the
extension switches in the PHP card have no effect on it, and an image based on the Envoryx image of
another runtime is pointed out too.
What’s missing shows up as The image lacks what Envoryx expects, each line saying what won’t work, for example socat is missing: no waiting for the database at start and SSH port forwarding. It’s a warning, not a refusal: Envoryx uses the image anyway. When nothing is missing, the row says everything Envoryx needs is there.
Private registries
Section titled “Private registries”For an image behind a login, an instance admin adds the registry under Settings → Private
registries with Add login: the host (ghcr.io, registry.example.com:5000, or docker.io
for Docker Hub), a username and a password or token. For GHCR that’s a token with read:packages.
Envoryx uses the login for pulls and hands it to builds for their FROM images, so a Dockerfile
can start from a private base image too. The password is never shown again; saving the card
without one keeps the stored one. If you set an image that can’t be pulled for lack of a login,
the error points you to this card. Once the login is there, save the same image on the project
again: Envoryx then pulls it, checks it and puts it in place. A Restart does the same.
Who may do what, and the manifest
Section titled “Who may do what, and the manifest”Setting an image or going back to the Envoryx image needs the admin role in the project, like changing a runtime. Developers can Rebuild without cache. Built images nobody uses any more show up on the Docker page with the other unused images; images from your registries are never removed by Envoryx.
In envoryx.yml each runtime takes image: or
dockerfile:, never both:
php: version: "8.4" dockerfile: .envoryx/php.Dockerfilenode: version: "24" image: ghcr.io/acme/node-tools:24Git operations and templates keep using the Envoryx image, by the way. They need its tools, and a Dockerfile from the repository doesn’t exist before the clone.