Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
2 tasks done
muellerst-hg opened this issue Jul 8, 2024 · 5 comments
Open
2 tasks done
Labels
defect Something isn't working in triage

Comments

@muellerst-hg
Copy link
Contributor

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 4ba0876

Steps to Reproduce

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

services:
  dtrack-frontend:
    image: dependencytrack/frontend:snapshot
    environment:
      - "API_BASE_URL=http://localhost:8081"
    ports:
      - "8080:8080"
    read_only: true
    volumes:
      - type: tmpfs
        target: /tmp
  1. Start the container:
docker compose -f compose-snapshot.yml up

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:
      - "API_BASE_URL=http://localhost:8181"
    ports:
      - "8180:8180"
    read_only: true
    volumes:
      - type: tmpfs
        target: /tmp
  1. Start the container:
docker compose -f compose-4_11_4.yml up

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

@muellerst-hg muellerst-hg added defect Something isn't working in triage labels Jul 8, 2024
@nscuro
Copy link
Member

nscuro commented Jul 8, 2024

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

@Squixx
Copy link
Contributor

Squixx commented Jul 8, 2024

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)

nginxinc/docker-nginx-unprivileged#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
Copy link
Contributor

Squixx commented Jul 19, 2024

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

@muellerst-hg
Copy link
Contributor Author

muellerst-hg commented Jul 23, 2024

@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
Copy link
Contributor

Squixx commented Jul 23, 2024

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defect Something isn't working in triage
Projects
None yet
Development

No branches or pull requests

3 participants