<p>I have an nginx web server deployed with docker swarm, and I want to be able to deploy it also with kubernetes.</p>
<p>Right now I'm having trouble inserting the nginx configuration files into the container.</p>
<p>I'll first post here what I already do in docker swarm, and then what I tried in kubernetes.</p>
<p><code>Dockerfile</code>:</p>
<pre><code>FROM    &quot;nginx:1.19.1-alpine&quot;   AS nginx
[...]
RUN                                                             \
        rm -fv  /etc/nginx/nginx.conf                           &amp;&amp; \
        ln -svT /usr/local/etc/nginx/nginx.conf                 \
                /etc/nginx/nginx.conf                           &amp;&amp; \
        rm -frv /etc/nginx/conf.d                               &amp;&amp; \
        ln -svT /usr/local/etc/nginx/conf.d                     \
                /etc/nginx/conf.d
[...]
</code></pre>
<p>Basically I set up the image so that I can place my custom nginx config files into <code>/usr/local/etc/</code> instead of <code>/etc/</code></p>
<p>Docker swarm:</p>
<p><code>docker-compose.yaml</code>:</p>
<pre><code>configs:
    nginx_conf:
        file: /run/configs/www/etc/nginx/nginx.conf
    nginx_conf_security-parameters:
        file: /run/configs/www/etc/nginx/conf.d/security-parameters.conf
    nginx_conf_server:
        file: /run/configs/www/etc/nginx/conf.d/server.conf

networks:
    alejandro-colomar:

services:
    www:
        configs:
        -
            mode: 0440
            source: nginx_conf
            target: /usr/local/etc/nginx/nginx.conf
        -
            mode: 0440
            source: nginx_conf_security-parameters
            target: /usr/local/etc/nginx/conf.d/security-parameters.conf
        -
            mode: 0440
            source: nginx_conf_server
            target: /usr/local/etc/nginx/conf.d/server.conf
        deploy:
            placement:
                constraints:
                -   node.role == worker
            replicas: 1
            restart_policy:
                condition: any
        image: &quot;alejandrocolomar/www:0.16-a6-kube&quot;
        networks:
        -
            &quot;alejandro-colomar&quot;
        ports:
        -   &quot;32001:8080&quot;

version: &quot;3.8&quot;
</code></pre>
<p>Here I take the nginx custom config files, which I first put in <code>/run/configs/</code> with a script so that they are in ram, and introduce them in the container as configs in the right place (<code>/usr/local/etc/nginx/</code> and its subdir <code>conf.d/</code>).</p>
<p>I'd like to do the same in kubernetes, and I read that I should use a projected volume for that (if it's doable with normal volumes or in some other way, without having to use any dirty workarounds, I'm also open to that), so I tried the following (after seeing some examples which weren't very clear to me):</p>
<p><code>config.sh</code>:</p>
<pre><code>
kubectl create configmap &quot;nginx-conf-cm&quot;                        \
        --from-file &quot;/run/configs/www/etc/nginx/nginx.conf&quot;
kubectl create configmap &quot;nginx-conf-security-parameters-cm&quot;    \
        --from-file &quot;/run/configs/www/etc/nginx/conf.d/security-parameters.conf&quot;
kubectl create configmap &quot;nginx-conf-server-cm&quot;                 \
        --from-file &quot;/run/configs/www/etc/nginx/conf.d/server.conf&quot;
</code></pre>
<p><code>deployment.yaml</code>:</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
    name: www-deploy
spec:
    replicas: 1
    selector:
        matchLabels:
            service: www-svc
    template:
        metadata:
            labels:
                service: www-svc
        spec:
            containers:
            -
                image: &quot;alejandrocolomar/www:0.16-a6-kube&quot;
                name: www-container
                volumeMounts:
                -
                    mountPath: /usr/local/etc/nginx/
                    name: nginx-volume
                    readOnly: true
            volumes:
            -
                name: nginx-volume
                projected:
                    sources:
                    -
                        configMap:
                            name: nginx-conf-cm
                            path: &quot;nginx.conf&quot;
                    -
                        configMap:
                            name: nginx-conf-security-parameters-cm
                            path: &quot;conf.d/security-parameters.conf&quot;
                    -
                        configMap:
                            name: nginx-conf-server-cm
                            path: &quot;conf.d/server.conf&quot;

</code></pre>
<p><code>service.yaml</code>: (This one I put it here only for completeness)</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
    name: www
spec:
    ports:
    -
        nodePort: 32001
        port: 8080
    selector:
        service: www-svc
    type: NodePort
</code></pre>
<p>The deployment failed, of course, but it wasn't very wrong I think.  When I entered in the container to debug it, the problem was that the three files were placed into <code>/usr/local/etc/nginx/</code>, and the subdir <code>conf.d/</code> was not created:</p>
<pre><code>/usr/local/etc/nginx/nginx.conf
/usr/local/etc/nginx/security-parameters.conf
/usr/local/etc/nginx/server.conf
</code></pre>
<p>How should I fix that (presumably in <code>deployment.yaml</code>) so that I have the following files in the container?:</p>
<pre><code>/usr/local/etc/nginx/nginx.conf
/usr/local/etc/nginx/conf.d/security-parameters.conf
/usr/local/etc/nginx/conf.d/server.conf
</code></pre>

<p>There are multiple ways to handle this. One solution would be to create 3 separate volumes from these individual config maps and mount each one into its appropriate destination file/folder.</p>
<pre><code>volumes:
        - name: nginx-cm
          configMap:
              name: nginx-conf-cm
        - name: nginx-sec
          configMap:
              name: nginx-conf-security-parameters-cm
        - name: nginx-serv
          configMap:
              name: nginx-conf-server-cm

        ...
        containers:
            -
                image: &quot;alejandrocolomar/www:0.16-a6-kube&quot;
                name: www-container
                volumeMounts:
                -   mountPath: /usr/local/etc/nginx/nginx.conf
                    name: nginx-cm
                    subPath: nginx.conf
                    readOnly: true
                -   mountPath: /usr/local/etc/nginx/conf.d/security-parameters.conf
                    name: nginx-sec
                    subPath: security-parameters.conf
                    readOnly: true
                -   mountPath: /usr/local/etc/nginx/conf.d/server.conf
                    name: nginx-serv
                    subPath: server.conf
                    readOnly: true

</code></pre>
<p>using <code>mountPath</code> and <code>subPath</code> in <code>volumeMounts</code> allows you to pick specific file from a given config map (doesn't matter much since you have on file per cm) and mount it as a file (not overriding the other content in the existing folder).</p>
<p>To explain a bit the code above:</p>
<pre><code>-   mountPath: /usr/local/etc/nginx/nginx.conf
    name: nginx-cm
    subPath: nginx.conf
</code></pre>
<p>tells kubernetes to use volume with the <code>name</code> of <code>nignx-cm</code> (defined in a volume section). Pick file <code>nginx.conf</code> (via <code>subpath</code>) that can be found in the associated config map and expose it in the container (<code>mountPath</code>) at the location <code>/usr/local/etc/nginx/nginx.conf</code>.</p>
<p><em>I have not run the code so there might be typos</em></p>
<p>PS: note that it might be better to create a custom configuration file inside of <code>../etc/nginx/conf.d/</code> instead of overriding <code>../etc/nginx/nginx.conf</code>. That way you wouldn't need to worry about destroying the original files <code>../etc/nginx/</code> and you could mount the whole volume instead of using <code>subpath</code> (to avoid issues with config updates)</p>
