🚀 Feature: update default docker compose example with additional security settings #577

Open
opened 2026-02-04 20:32:01 +03:00 by OVERLORD · 4 comments
Owner

Originally created by @James18232 on GitHub (Dec 30, 2025).

Feature description

Request to update the default docker compose example to include read_only: true and
security_opt: - no-new-privileges:true flags.

bonus if you want to add a cap_drop: all and cap_add for required capabilities only.

Pitch

This seems like a good idea from a hardening perspective and shouldn't impact the function of the container.

the distroless image is also an option, but i dont think this needs to be the default and these changes should in theory make the full fat image more secure by default..

Originally created by @James18232 on GitHub (Dec 30, 2025). ### Feature description Request to update the default docker compose example to include `read_only: true` and `security_opt: - no-new-privileges:true` flags. bonus if you want to add a cap_drop: all and cap_add for required capabilities only. ### Pitch This seems like a good idea from a hardening perspective and shouldn't impact the function of the container. the distroless image is also an option, but i dont think this needs to be the default and these changes should in theory make the full fat image more secure by default..
Author
Owner

@Im-hsh commented on GitHub (Jan 3, 2026):

Yeah, actually running pocketID with these settings for a while, been working great so far.

services:
  pocket-id:
    image: ghcr.io/pocket-id/pocket-id:latest-distroless
    container_name: pocketid
    restart: unless-stopped
    user: 1000:1000
    read_only: true
    security_opt:
      - no-new-privileges=true
    tty: false
    stdin_open: false
    cap_drop:
      - ALL
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=256m
    networks:
      - auth_net
    #    ports:
    #      - 1411:1411
    environment:
      - APP_URL=https://pocketid.mydomain.com
      - TRUST_PROXY=true # Enables reverse proxy support
      - ENCRYPTION_KEY=<<KEY>> # generate with: openssl rand -base64 32
      - ANALYTICS_DISABLED=true
    volumes:
      - /srv/docker/pocketid/data:/app/data
networks:
  auth_net:
    external: true
@Im-hsh commented on GitHub (Jan 3, 2026): Yeah, actually running pocketID with these settings for a while, been working great so far. ```yaml services: pocket-id: image: ghcr.io/pocket-id/pocket-id:latest-distroless container_name: pocketid restart: unless-stopped user: 1000:1000 read_only: true security_opt: - no-new-privileges=true tty: false stdin_open: false cap_drop: - ALL tmpfs: - /tmp:rw,noexec,nosuid,nodev,size=256m networks: - auth_net # ports: # - 1411:1411 environment: - APP_URL=https://pocketid.mydomain.com - TRUST_PROXY=true # Enables reverse proxy support - ENCRYPTION_KEY=<<KEY>> # generate with: openssl rand -base64 32 - ANALYTICS_DISABLED=true volumes: - /srv/docker/pocketid/data:/app/data networks: auth_net: external: true ```
Author
Owner

@James18232 commented on GitHub (Jan 3, 2026):

@Im-hsh what is your reason for including a tmpfs for /tmp? This is not needed from my testing.. Is this a requirement due to a tweak to the distroless variant?

I also needed a SETGID cap due to running as root in the container (rootless docker). Setting a non root user removes this requirement - but need to be mindful of permissions on the host. userns-remaps trip me up at times..

@James18232 commented on GitHub (Jan 3, 2026): @Im-hsh what is your reason for including a tmpfs for /tmp? This is not needed from my testing.. Is this a requirement due to a tweak to the distroless variant? I also needed a SETGID cap due to running as root in the container (rootless docker). Setting a non root user removes this requirement - but need to be mindful of permissions on the host. userns-remaps trip me up at times..
Author
Owner

@Im-hsh commented on GitHub (Jan 3, 2026):

It’s an optional hardening step not a must-have, but I personally add it to all my containers for two reasons:

  1. When I set read_only=true some containers needs a writable tmp directory so I pass this RAM only /tmp with noexec nosuid nodev parameters to restrict any potential escalation or execution of binaries/malware/scrpt/...

  2. Even without read_only I keep the tmpfs because it costs one line and zero disk I/O and If an exploit ever writes a payload to /tmp it can’t be executed and disappears the moment the container stops

So I keep it all the time as a standard practice or security habit. It's a second line of defense with no downside I guess.

But to be clear I'm not a cyber security professional by any means :) I'm just reading and searching alot.

For, SETGID cap , I didn't really understood your situation, I set my container to run as user 1000 and gave directory permission to that user before 'up' the container

sudo chown -R $USER:$USER /srv/docker/pocketid
@Im-hsh commented on GitHub (Jan 3, 2026): It’s an optional hardening step not a must-have, but I personally add it to all my containers for two reasons: 1. When I set read_only=true some containers needs a writable tmp directory so I pass this RAM only /tmp with noexec nosuid nodev parameters to restrict any potential escalation or execution of binaries/malware/scrpt/... 2. Even without read_only I keep the tmpfs because it costs one line and zero disk I/O and If an exploit ever writes a payload to /tmp it can’t be executed and disappears the moment the container stops So I keep it all the time as a standard practice or security habit. It's a second line of defense with no downside I guess. But to be clear I'm not a cyber security professional by any means :) I'm just reading and searching alot. For, SETGID cap , I didn't really understood your situation, I set my container to run as user 1000 and gave directory permission to that user before 'up' the container ``` sudo chown -R $USER:$USER /srv/docker/pocketid ```
Author
Owner

@James18232 commented on GitHub (Jan 3, 2026):

@Im-hsh thanks. I believe the tmpfs can be left out of the docs then as not strictly needed - best to keep it simple.

re SETGID, a feature? of rootless docker is that it uses a userns-remap, so files in the container owned by user 1000 will be owned by a different user on the host - this can catch people out. If i knew at the time you could enable userns-remap on rootful docker i would not have bothered with rootless docker at all but hey thats learning for you.

i'm also learning :) but i think tmpfs is a false sense of security if not needed - just gives another rw area at runtime. I understand noexec won't stop use of interpreters such as bash or sh from working in /tmp in this scenario - you are distroless with no interpreter though. There is always other rw areas needed for a container to function which also present a similar risk.

More important is limiting network access - using internal:true for example. Not as much out there in that space for more complex setups and not trivial with current docker networking capabilities and limitations.

@James18232 commented on GitHub (Jan 3, 2026): @Im-hsh thanks. I believe the tmpfs can be left out of the docs then as not strictly needed - best to keep it simple. re SETGID, a feature? of rootless docker is that it uses a userns-remap, so files in the container owned by user 1000 will be owned by a different user on the host - this can catch people out. If i knew at the time you could enable userns-remap on rootful docker i would not have bothered with rootless docker at all but hey thats learning for you. i'm also learning :) but i think tmpfs is a false sense of security if not needed - just gives another rw area at runtime. I understand noexec won't stop use of interpreters such as bash or sh from working in /tmp in this scenario - you are distroless with no interpreter though. There is always other rw areas needed for a container to function which also present a similar risk. More important is limiting network access - using internal:true for example. Not as much out there in that space for more complex setups and not trivial with current docker networking capabilities and limitations.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/pocket-id#577