DependencyTrack / frontend

Frontend UI for Dependency-Track
https://dependencytrack.org/
Apache License 2.0
100 stars 146 forks source link

container fails to start when using readonly filesystem (20-envsubst-on-templates.sh) #940

Open muellerst-hg opened 2 months ago

muellerst-hg commented 2 months ago

Current Behavior

When mounting the root filesystem with read_only, the entrypoint script 20-envsubst-on-templates.sh fails to start with the following error:

dtrack-frontend-snapshot-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
dtrack-frontend-snapshot-1  | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf
dtrack-frontend-snapshot-1  | /docker-entrypoint.d/20-envsubst-on-templates.sh: line 53: can't create /etc/nginx/conf.d/default.conf: Read-only file system

Tested with image: dependencytrack/frontend:snapshot (image id 1b096cd8f5da)

Readonly root filesystem is working fine using image dependencytrack/frontend:4.11.4 (image id c3d304f8c999)

Seems like this was introduced with 4ba087690a74f5f1eb302b17142137b233434c2b

Steps to Reproduce

  1. Create a file compose-snapshot.yml with the following content:
    
    version: "3"

services: dtrack-frontend: image: dependencytrack/frontend:snapshot environment:

dtrack-frontend-snapshot-1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration dtrack-frontend-snapshot-1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ dtrack-frontend-snapshot-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh dtrack-frontend-snapshot-1 | 10-listen-on-ipv6-by-default.sh: info: can not modify /etc/nginx/conf.d/default.conf (read-only file system?) dtrack-frontend-snapshot-1 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh dtrack-frontend-snapshot-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh dtrack-frontend-snapshot-1 | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf dtrack-frontend-snapshot-1 | /docker-entrypoint.d/20-envsubst-on-templates.sh: line 53: can't create /etc/nginx/conf.d/default.conf: Read-only file system dtrack-frontend-snapshot-1 exited with code 1


### Expected Behavior

I expect root filesystem with readonly to work as before (in 4.11.4):

1. Create a file `compose-4_11_4.yml` with the following content:

version: "3"

services: dtrack-frontend-4-11-4: image: dependencytrack/frontend:4.11.4 environment:

dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh dtrack-frontend-4-11-4-1 | 10-listen-on-ipv6-by-default.sh: info: can not modify /etc/nginx/conf.d/default.conf (read-only file system?) dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-oidc-configuration.sh dtrack-frontend-4-11-4-1 | 30-oidc-configuration.sh: info: can not modify config.json - ENV configuration will be ignored dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh dtrack-frontend-4-11-4-1 | /docker-entrypoint.sh: Configuration complete; ready for start up dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: using the "epoll" event method dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: nginx/1.25.5 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: built by gcc 13.2.1 20231014 (Alpine 13.2.1_git20231014) dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: OS: Linux 5.15.133.1-microsoft-standard-WSL2 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1024:1048576 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker processes dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 24 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 25 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 26 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 27 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 28 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 29 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 30 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 31 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 32 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 33 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 34 dtrack-frontend-4-11-4-1 | 2024/07/08 09:04:32 [notice] 1#1: start worker process 35



### Dependency-Track Frontend Version

4.12.0-SNAPSHOT

### Browser

Mozilla Firefox

### Browser Version

127.0.2

### Operating System

Linux

### Checklist

- [X] I have read and understand the [contributing guidelines](https://github.com/DependencyTrack/dependency-track/blob/master/CONTRIBUTING.md#filing-issues)
- [X] I have checked the [existing issues](https://github.com/DependencyTrack/frontend/issues) for whether this defect was already reported
nscuro commented 2 months ago

@Squixx Any idea how we can make your changes work with this requirement?

Squixx commented 2 months ago

I'm on vacation right now, so can't check. But seems like it has to with the way nginx converts the template to actual config on boot. I'll take a look when I get back (~17th July)

https://github.com/nginxinc/docker-nginx-unprivileged/issues/88 could point that it's an issue with the inner workings of nginx, you could ensure the entire conf file is outside of the container like https://gist.github.com/monosoul/e462b03cba5542bfc52f135417a8209d in the case of read_only: true to ensure it works both ways.

Which makes me think we could solve this by only adding specific docs about read only.

But again I'm on mobile so have no way to test as of right now.

Squixx commented 1 month ago

muellerst-hg does it work for you with the above gist?

muellerst-hg commented 1 month ago

@Squixx even though 20-envsubst-on-templates.sh entrypoint does its job when applying this gist. The nginx config which is used is a bit different. I am not sure if this an issue. curl http://127.0.0.1:8080 returns the expected index.html file.

# config fetched from container process using nginx -T
diff -wu /tmp/rw.conf /tmp/ro.conf

--- /tmp/rw.conf        2024-07-23 12:55:26.722236147 +0200
+++ /tmp/ro.conf        2024-07-23 12:55:24.402242094 +0200
@@ -140,7 +140,10 @@
     video/x-msvideo                                  avi;
 }

-# configuration file /etc/nginx/conf.d/default.conf:
+# configuration file /etc/nginx/conf.d/10-include-tmp.conf:
+include /var/nginx.conf.d/*.conf;
+
+# configuration file /var/nginx.conf.d/default.conf:
 server {
   listen      8080;
   server_name _;
@@ -160,3 +163,49 @@
     root /usr/share/nginx/html;
   }
 }
+# configuration file /etc/nginx/conf.d/default.conf:
+server {
+    listen       8080;
+    server_name  localhost;
+
+    #access_log  /var/log/nginx/host.access.log  main;
+
+    location / {
+        root   /usr/share/nginx/html;
+        index  index.html index.htm;
+    }
+
+    #error_page  404              /404.html;
+
+    # redirect server error pages to the static page /50x.html
+    #
+    error_page   500 502 503 504  /50x.html;
+    location = /50x.html {
+        root   /usr/share/nginx/html;
+    }
+
+    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
+    #
+    #location ~ \.php$ {
+    #    proxy_pass   http://127.0.0.1;
+    #}
+
+    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+    #
+    #location ~ \.php$ {
+    #    root           html;
+    #    fastcgi_pass   127.0.0.1:9000;
+    #    fastcgi_index  index.php;
+    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
+    #    include        fastcgi_params;
+    #}
+
+    # deny access to .htaccess files, if Apache's document root
+    # concurs with nginx's one
+    #
+    #location ~ /\.ht {
+    #    deny  all;
+    #}
+}
+
+

Here's the setup I have tested:

$ echo "include /var/nginx.conf.d/*.conf;" > include-tmp.conf
$ cat > compose.yml << EOF
version: "3.9"

services:
  dtrack-frontend-snapshot:
    image: dependencytrack/frontend:snapshot
    environment:
      - BASE_PATH=http://127.0.0.1:8080
      - NGINX_ENVSUBST_OUTPUT_DIR=/var/nginx.conf.d
    ports:
      - "8080:8080"
    read_only: true
    volumes:
      - type: tmpfs
        target: /tmp
      - ./include-tmp.conf:/etc/nginx/conf.d/10-include-tmp.conf:ro
    tmpfs:
      - /var/nginx.conf.d:rw,noexec,nosuid,nodev
 EOF

IMHO this is a non-intuitive workaround which requires knowledge about implementation details in order to understand what one is doing. Nevertheless I agree, this is an upstream issue of docker-nginx-unprivileged because they do not cleanly separate default configs/templates and rendered config. An nginx container image which serves static files should by default run unpriv. with a readonly filesystem. The upstream entrypoint scripts are failing here.

Squixx commented 1 month ago

Yeah i agree, this requires some docker / nginx knowledge to get to run properly... but currently has no alternative unfortunately. @nscuro how do you want to approach this? could we write some docs for this usecase?