# Docker image: included software

**URL:** https://community.silverbullet.md/t/docker-image-included-software/1931
**Category:** Ideas
**Created:** [March 8, 2025, 9:27am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931 "2025-03-08T09:27:35Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![MatthiasBenaets](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@MatthiasBenaets](https://community.silverbullet.md/u/MatthiasBenaets)
#### Post date: [May 8, 2025, 3:38pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/21 "2025-05-08T15:38:18Z")

</div>

I’m no Docker expert, but how about using an env file and pulling a list of packages into the Dockerfile as a variable. Will this not be cached if nothing changes?

Atm I just use this in my docker compose file, it however reinstalls the packages on rebuild:

```auto
    entrypoint: >
      /bin/bash -c "apt-get update && apt-get install -y hello && /tini -- /docker-entrypoint.sh"

```

---

<div class="post-metadata">

### Author: ![LumenYoung](https://community.silverbullet.md/user_avatar/community.silverbullet.md/lumenyoung/32/368_2.png) [@LumenYoung](https://community.silverbullet.md/u/LumenYoung)
#### Post date: [May 9, 2025, 8:28am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/22 "2025-05-09T08:28:10Z")

</div>

I think pandoc is such a small dependency (this size seems numb for us Deep Learning Engineers where most of the image can be of the size of 10 GBs). I would suggest simply add them when building the image.

Also when we were using it for the first time with a fresh container, downloading it would always introduce some delay that is somewhat not ideal and also may confuse not that tech-savvy user and blame SB. On either side I don’t see any benefit to use apt install on demand.

Projecting from my own experience with self-hosting. The size of SB image (1.17GB for now) + texlive and pandoc would normally have no impact on the end user. But suppose there is such usecase which I’m not aware of, it is also possible to provide additional ci with additional tag that provides slim version of the image building without texlive. This way those users are catered for their special need and most of the people are defaulted to the image that serves the best user experience.

After all, the space/RAM left available are the space/RAM wasted 😄

---

<div class="post-metadata">

### Author: ![bnjbvr](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bnjbvr/32/345_2.png) [@bnjbvr](https://community.silverbullet.md/u/bnjbvr)
#### Post date: [May 9, 2025, 8:56am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/23 "2025-05-09T08:56:23Z")

</div>

An alternative for including extra applications might be to use two docker images:

- keep the one for silverbullet
- add one for extra statically-linked apps
- make them share a volume: in the first image it’s bound to a directory that’s in $PATH, in the second that’s bound to `/usr/bin` or something similar.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [May 9, 2025, 11:58am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/24 "2025-05-09T11:58:53Z")

</div>

It seems the docker image build times have increased from 3-5min to 8min since adding pdflatex and pandoc, which is something I don’t like. Haven’t checked the image size increase, but it’s probably also quite a bit. So still looking at how take this out again, and install such packages more on the fly. So keep the possible solutions going 🙂

---

<div class="post-metadata">

### Author: ![MrMugame](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mrmugame/32/358_2.png) [@MrMugame](https://community.silverbullet.md/u/MrMugame)
#### Post date: [May 12, 2025, 10:21am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/25 "2025-05-12T10:21:35Z")

</div>

The „docker“ way would be to basically fork the image and create a new immutable image. Using docker compose this can be done fairly easily.

```yaml
services:
  silverbullet:
    build:
      context: .
      dockerfile_inline: |
        FROM ghcr.io/silverbulletmd/silverbullet:v2

        RUN apt-get update && \
            apt-get install -y pandoc

```

Frankly I haven‘t tested that, but something like that should work. This also allows copying static binaries into the image the user may have created themselves.

---

<div class="post-metadata">

### Author: ![LumenYoung](https://community.silverbullet.md/user_avatar/community.silverbullet.md/lumenyoung/32/368_2.png) [@LumenYoung](https://community.silverbullet.md/u/LumenYoung)
#### Post date: [May 12, 2025, 12:33pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/26 "2025-05-12T12:33:20Z")

</div>

I’ve been using docker compose for 5 years and this is the first time I know that I can have inline fork of an Image. That is pretty amazing thanks!

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 8, 2025, 11:58am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/27 "2025-06-08T11:58:58Z")

</div>

> <https://github.com/silverbulletmd/silverbullet/issues/1419>
>
> Currently I pre-bundle a few debian packages in the v2 Docker image like pdflate…x and pandoc. This is making the image quite large. It'd be nicer to have a declarative Lua API that installs such packages on demand. Since I also plan to support binary distributions for at least Linux and macOS systems (#1418), it would be nice to make this somehow independent of package managers.
> 
> Some conceptual API ideas:
> 
> \`\`\`lua
> 
> packages = {}
> 
> packages.pandoc = {
> macOS = {
> install = "brew install pandoc",
> check = "which pandoc",
> },
> debian = {
> install = "apt install -y pandoc",
> check = "which pandoc",
> }
> }
> 
> package.ensureInstalled {"pandoc"}
> \`\`\`

---

<div class="post-metadata">

### Author: ![LumenYoung](https://community.silverbullet.md/user_avatar/community.silverbullet.md/lumenyoung/32/368_2.png) [@LumenYoung](https://community.silverbullet.md/u/LumenYoung)
#### Post date: [June 8, 2025, 1:42pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/28 "2025-06-08T13:42:30Z")

</div>

Cool! that could also be an option. Meanwhile could just add a field in config section to specify which tool to `ensure_installed` when SB spawns.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 8, 2025, 2:14pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/29 "2025-06-08T14:14:51Z")

</div>

Yeah, but that would assume the packages have the same name in every package manager.

---

<div class="post-metadata">

### Author: ![LumenYoung](https://community.silverbullet.md/user_avatar/community.silverbullet.md/lumenyoung/32/368_2.png) [@LumenYoung](https://community.silverbullet.md/u/LumenYoung)
#### Post date: [June 8, 2025, 4:38pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/30 "2025-06-08T16:38:29Z")

</div>

Yeah, but that can be implemented to check if it is only inside the container rather than using it on directly installation. I think this is only reasonable to support if inside our own image.

Also if you were to install from different package manegers (I mean install from npm, pip or apt), we can make the installation be not a list rather a table of lists like following:

```lua
ensure_installed = {
  apt = { "pdflatex", "pandoc"},
  pip = { "torch", "httpx"}
}

```

With limited support for only a few package manager.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 8, 2025, 5:29pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/31 "2025-06-08T17:29:33Z")

</div>

Actually this is a bit more complicated than I considered. My first thought: oh right, we can only do this in a container because we don’t have root rights outside of it (and it’s questionable if you’d want to just have SB install “random” software on your host machine). But then I realized that even in the container SB doesn’t run as root…

Perhaps the @MrMugame strategy is still the more viable one…

Alternatively we can use a “user land” package manager, like [Nix](https://nixos.org) but honestly I think this adds a lot of complexity and scope to SilverBullet that I’m not really excited to add.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 9, 2025, 8:26am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/32 "2025-06-09T08:26:49Z")

</div>

Ok, I just ported the v2 Docker image to be based on Alpine and I removed pandoc. This resizes the docker images from 1.7GB (!!) to 300mb or something around that.

To add pandoc or other custom packages, do what @MrMugame suggests:

In your compose.yml file:

```auto
   build:
      context: .
      dockerfile_inline: |
        FROM ghcr.io/silverbulletmd/silverbullet:v2
        RUN apk add pandoc 

```

This what I have on my instance now, seems to work well.

---

<div class="post-metadata">

### Author: ![LumenYoung](https://community.silverbullet.md/user_avatar/community.silverbullet.md/lumenyoung/32/368_2.png) [@LumenYoung](https://community.silverbullet.md/u/LumenYoung)
#### Post date: [June 9, 2025, 8:57am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/33 "2025-06-09T08:57:57Z")

</div>

This looks cool. But also means this installation approach is highly confined to tech-savvy people. But seems not very demanding for the target audience of SB.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 9, 2025, 9:28am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/34 "2025-06-09T09:28:50Z")

</div>

Yes, but I think we have to accept that SB is already targeted at tech savvy people. And it’s likely this audience that may want to install additional packages inside a container.

---

<div class="post-metadata">

### Author: ![MatthiasBenaets](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@MatthiasBenaets](https://community.silverbullet.md/u/MatthiasBenaets)
#### Post date: [June 10, 2025, 12:30pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/35 "2025-06-10T12:30:03Z")

</div>

Please correct me if I’m wrong, I’m not an expert in this area.

From what I understand, the `denoland/deno:alpine` container uses the glibc library. After some testing, it seems this can cause conflicts when running binaries installed via `apk`, since Alpine packages are typically compiled against musl.

A simple example you can try: `apk add ripgrep && rg -h`

This kind of issue likely affects any binary that depends on musl-linked libraries.

As far as I can tell, the only workaround would be to manually compile these packages against glibc, but I haven’t tested it yet, and frankly, it sounds like a painful and suboptimal solution, especially in a docker-compose setup.

If there’s no clean fix for this, I would suggest switching to the `denoland/deno:ubuntu` image instead. It’s only about 90MB larger. While I appreciate lightweight containers, storage is cheap, and I’d much rather have something that just works.

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 10, 2025, 1:38pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/36 "2025-06-10T13:38:34Z")

</div>

Interesting, I assumed that the Deno Alpine image only _added_ libc to the image, not removed musl so all Alpine software just works (pandoc and git seem fine). In this case I may just go with a plain ubuntu image, doesn’t need to even include Deno since I’m now adding the single binary builds to the docker image anyway.

Let me experiment a bit

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 10, 2025, 2:08pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/37 "2025-06-10T14:08:51Z")

</div>

Ok, I built a few versions based on different images:

- Deno’s Alpine image + git: 326MB
- Debian slim + git: 431MB
- Ubuntu latest + git: 402MB

Personally I’m more aligned with Debian in terms of philosophy than with Ubuntu, but not sure if I’m 30MB more aligned 😉

---

<div class="post-metadata">

### Author: ![Maarrk](https://community.silverbullet.md/user_avatar/community.silverbullet.md/maarrk/32/56_2.png) [@Maarrk](https://community.silverbullet.md/u/Maarrk)
#### Post date: [June 10, 2025, 4:18pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/38 "2025-06-10T16:18:08Z")

</div>

I think that Ubuntu is so much more popular than Debian that its `apt` quirks have become the norm now. So on the pragmatic side I expect less issues for users (and issue reports for you) if you go with Ubuntu. I would’ve said the same even if the 7% difference were the other way

At least this has been my experience on desktop which sadly made me switch back after testing Debian for a few weeks.

* * *

In the perfect world, Deno would build with musl when packaging for Alpine, but alas I can’t be bothered (nor trusted) to make this container myself…

---

<div class="post-metadata">

### Author: ![MatthiasBenaets](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@MatthiasBenaets](https://community.silverbullet.md/u/MatthiasBenaets)
#### Post date: [June 10, 2025, 4:28pm UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/39 "2025-06-10T16:28:22Z")

</div>

I’m good with either. I myself, run more Debian instances than Ubuntu; but I can understand why people would prefer a more up-to-date feature rich Ubuntu.  
I do have to agree with Marek. People will be more familiar with Ubuntu.

Appreciate you testing some different options! 🙂

---

<div class="post-metadata">

### Author: ![zef](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zef/32/7_2.png) [@zef](https://community.silverbullet.md/u/zef)
#### Post date: [June 12, 2025, 9:17am UTC](https://community.silverbullet.md/t/docker-image-included-software/1931/40 "2025-06-12T09:17:50Z")

</div>

Ok, so here’s what I have right now:

- I switched the base image to `ubuntu:noble` (the current LTS)
- I added an additional `SB_APT_PACKAGES` environment variable. You can set this to a list of additional ubuntu packages you’d like to install at runtime, e.g. `SB_APT_PACKAGES="pandoc ripgrep"` if set, the docker image _when booted_ will do an `apt update && apt install -y $SB_APT_PACKAGES`. By default this happens asynchronously (so the server is already running, and the installation happens in the background) although you can override this behavior by setting SB\_APT\_SYNC.

You can still use the custom base image method, but the environment variable is probably user friendlier.

[Previous page](https://community.silverbullet.md/t/docker-image-included-software/1931.md?page=1)

[Next page](https://community.silverbullet.md/t/docker-image-included-software/1931.md?page=3)
