diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f400297 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +FROM jc21/alpine-nginx-full:node +LABEL maintainer="Jamie Curnow " + +ENV SUPPRESS_NO_CONFIG_WARNING=1 +ENV S6_FIX_ATTRS_HIDDEN=1 +ENV NODE_ENV=production + +RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \ + && apk update \ + && apk add python3 certbot jq \ + && python3 -m ensurepip \ + && rm -rf /var/cache/apk/* + +# s6 overlay +COPY scripts/install-s6 /tmp/install-s6 +RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6 + +EXPOSE 80 +EXPOSE 81 +EXPOSE 443 + +ADD backend /app +ADD frontend/dist /app/frontend +COPY global /app/global + +WORKDIR /app +RUN yarn install + +# add late to limit cache-busting by modifications +COPY docker/rootfs / + +# Remove frontend service not required for prod, dev nginx config as well +RUN rm -rf /etc/services.d/frontend +RUN rm -f /etc/nginx/conf.d/dev.conf + +VOLUME [ "/data", "/etc/letsencrypt" ] +ENTRYPOINT [ "/init" ] + +HEALTHCHECK --interval=5s --timeout=3s CMD /bin/check-health \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..60de491 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,86 @@ +# docker-compose.yml +version: "3.7" + +secrets: + # paths assume the .secrets folder is sibling depth to folder where docker-compose resides + DB_ROOT_PWD: + file: ../.secrets/db_root_pwd.txt + MYSQL_PWD: + file: ../.secrets/mysql_pwd.txt + +# networks: +# npm-bridge: # arbitrary name +# driver: bridge + +services: + mariadb: + image: ahgraber/mariadb-aria:test + container_name: mariadb + secrets: + - DB_ROOT_PWD + - MYSQL_PWD + # networks: + # - npm-bridge + # ports: + # - 3306:3306 + environment: + # MYSQL_ROOT_PASSWORD: "npm" + MYSQL_ROOT_PASSWORD__FILE: /run/secrets/DB_ROOT_PWD + MYSQL_DATABASE: "npm" + MYSQL_USER: "npm" + # MYSQL_PASSWORD: "npm" + MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD + volumes: + - ./data/mysql:/var/lib/mysql + # - npm-mount:/var/lib/mysql + # restart: unless-stopped + + npm: + build: + context: . + dockerfile: ./Dockerfile + # args: + # TARGETPLATFORM: arm64v8 + image: nginx-proxy-manager:test # provide a name and tag for the image + container_name: npm + secrets: + - MYSQL_PWD + # networks: + # - npm-bridge + ports: + - 8080:80 + - 8443:443 + - 8888:81 + environment: + DISABLE_IPV6: 'true' + DB_MYSQL_HOST: "mariadb" + DB_MYSQL_PORT: 3306 + DB_MYSQL_NAME: "npm" + DB_MYSQL_USER: "npm" + # DB_MYSQL_PASSWORD: "npm" + DB_MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD + # DB_MYSQL_PASSWORD: "sqlL3tm3in" + volumes: + - ./data/npm:/data + - ./data/letsencrypt:/etc/letsencrypt + # - npm-mount:/data + # - letsencrypt-mount:/etc/letsencrypt + depends_on: + - mariadb + # restart: unless-stopped + +# ## https://stackoverflow.com/questions/45282608/how-to-directly-mount-nfs-share-volume-in-container-using-docker-compose-v3 +# volumes: +# npm-mount: +# driver: local +# driver_opts: +# type: nfs +# o: nfsvers=4,addr=10.2.1.1,rw,retry=1,soft,nolock +# device: ":/npm" +# letsencrypt-mount: +# driver: local +# driver_opts: +# type: nfs +# o: nfsvers=4,addr=10.2.1.1,rw,retry=1,soft,nolock +# device: ":/letsencrypt" + \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index f243208..66bbd92 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -43,6 +43,6 @@ RUN yarn install RUN rm -rf /etc/services.d/frontend RUN rm -f /etc/nginx/conf.d/dev.conf VOLUME [ "/data", "/etc/letsencrypt" ] -CMD [ "/init" ] +ENTRYPOINT [ "/init" ] HEALTHCHECK --interval=5s --timeout=3s CMD /bin/check-health diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 9ac2911..cad4bc7 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -1,9 +1,9 @@ FROM jc21/alpine-nginx-full:node LABEL maintainer="Jamie Curnow " -ENV S6_LOGGING=0 ENV SUPPRESS_NO_CONFIG_WARNING=1 ENV S6_FIX_ATTRS_HIDDEN=1 +ENV NODE_ENV=production RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \ && apk update \ @@ -11,22 +11,24 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \ && python3 -m ensurepip \ && rm -rf /var/cache/apk/* -# Task -RUN cd /usr \ - && curl -sL https://taskfile.dev/install.sh | sh \ - && cd /root - -COPY rootfs / -RUN rm -f /etc/nginx/conf.d/production.conf - # s6 overlay -RUN curl -L -o /tmp/s6-overlay-amd64.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v1.22.1.0/s6-overlay-amd64.tar.gz" \ - && tar -xzf /tmp/s6-overlay-amd64.tar.gz -C / +COPY scripts/install-s6 /tmp/install-s6 +RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6 EXPOSE 80 EXPOSE 81 EXPOSE 443 -ENTRYPOINT [ "/init" ] +COPY docker/rootfs / +ADD backend /app +ADD frontend/dist /app/frontend +COPY global /app/global -HEALTHCHECK --interval=5s --timeout=3s CMD /bin/check-health +WORKDIR /app +RUN yarn install + +# Remove frontend service not required for prod, dev nginx config as well +RUN rm -rf /etc/services.d/frontend RUN rm -f /etc/nginx/conf.d/dev.conf + +VOLUME [ "/data", "/etc/letsencrypt" ] +ENTRYPOINT [ "/init" ] \ No newline at end of file diff --git a/docker/dev/docker-compose.yaml b/docker/dev/docker-compose.yaml index 1cc1bfa..3587196 100644 --- a/docker/dev/docker-compose.yaml +++ b/docker/dev/docker-compose.yaml @@ -28,8 +28,8 @@ services: npm: build: - context: ../ - dockerfile: ./dev/Dockerfile + context: ../../ + dockerfile: ./docker/dev/Dockerfile # args: # TARGETPLATFORM: arm64v8 image: npm:test # provide a name and tag for the image diff --git a/docker/rootfs/etc/cont-init.d/01_envfile.sh b/docker/rootfs/etc/cont-init.d/01_envfile.sh index be87c49..a0bc5ac 100644 --- a/docker/rootfs/etc/cont-init.d/01_envfile.sh +++ b/docker/rootfs/etc/cont-init.d/01_envfile.sh @@ -2,10 +2,11 @@ # ref: https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/cont-init.d/01-envfile # in s6, environmental variables are written as text files for s6 to monitor -for FILENAME in $(find /var/run/s6/container_environment/ | grep "^.*__FILE"); do - echo "[secret-init] Evaluating ${FILENAME}" +# seach through full-path filenames for files ending in "__FILE" +for FILENAME in $(find /var/run/s6/container_environment/ | grep "__FILE$"); do + echo "[secret-init] Evaluating ${FILENAME##*/}" - # set SECRETFILE to the contents of the variable + # set SECRETFILE to the contents of the full-path textfile SECRETFILE=$(cat ${FILENAME}) # SECRETFILE=${FILENAME} echo "[secret-init] Setting SECRETFILE to ${SECRETFILE}..." # DEBUG - rm for prod! @@ -13,16 +14,16 @@ for FILENAME in $(find /var/run/s6/container_environment/ | grep "^.*__FILE"); d # if SECRETFILE exists / is not null if [[ -f ${SECRETFILE} ]]; then # strip the appended "__FILE" from environmental variable name ... - STRIPFILE=$(echo $FILENAME | sed "s/__FILE//g") + STRIPFILE=$(echo ${FILENAME} | sed "s/__FILE//g") echo "[secret-init] Set STRIPFILE to ${STRIPFILE}" # DEBUG - rm for prod! - + # ... and set value to contents of secretfile # since s6 uses text files, this is effectively "export ..." - cat ${SECRETFILE} > ${STRIPFILE} + cat $(${SECRETFILE} | xargs) > ${STRIPFILE} echo "[secret-init] Set ${STRIPFILE} to $(cat ${STRIPFILE})" # DEBUG - rm for prod!" - echo "[secret-init] Success! ${STRIPFILE##*/} set from ${FILENAME##*/}" + echo "[secret-init] Success! ${STRIPFILE} set from ${FILENAME}" else - echo "[secret-init] cannot find secret in ${FILENAME##*/}" + echo "[secret-init] cannot find secret in ${FILENAME}" fi done