diff --git a/.gitignore b/.gitignore index ecb3871..4e42f48 100644 --- a/.gitignore +++ b/.gitignore @@ -130,6 +130,4 @@ dist .yarn/install-state.gz .pnp.* ignore -posts -templates data diff --git a/Dockerfile b/Dockerfile index 6f173ea..9c2f369 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,61 @@ -FROM node:21-alpine3.18 +# node image +FROM node:21-alpine3.18 as compiled WORKDIR /tmp +USER root + +# Copy the source code into the temp folder. COPY . /tmp -RUN yarn install --production -RUN yarn global add typescript + +# Installing the dependencies required for compiling. +RUN yarn install && yarn global add typescript + +# Compile the project FROM typescript INTO javascript RUN tsc -RUN mkdir /app -RUN cp -r /tmp/*.json /app -RUN cp -r /tmp/build/src /app -RUN cp -r /tmp/src/views /app/src/ -RUN cp -r /tmp/data.template/ /app/data.template -RUN cp -r /tmp/node_modules /app -COPY ./scripts/docker_run.sh /app/run.sh + +# Putting some stuff into the final build +RUN cp -r /tmp/*.json /tmp/build/ && \ + cp -r /tmp/data.template /tmp/build/ && \ + cp -r /tmp/src/views /tmp/build/src/ && \ + cp -r /tmp/data.template /tmp/build && \ + cp -r /tmp/scripts/docker_bootstrapper.sh /tmp/build/bootstrapper.sh && \ + cp -r /tmp/scripts/docker_run.sh /tmp/build/runner.sh + +# The final version of disseminate is now in /tmp/build + +FROM node:21-alpine3.18 as main_image + +# Create a volume for our data folder +VOLUME ["/app/data"] + +# Create a directory for our new app. +RUN mkdir -p /app + +# Switch to the directory. WORKDIR /app -CMD ["npm", "run", "docker:prod:run"] + +# Delete default node user for the next step. +RUN deluser node + +# We want to run disseminate as a non-root user. +ARG UID +ARG GID +RUN addgroup --gid $GID disseminate && \ + adduser --home /app --uid $UID -G disseminate --disabled-password disseminate + +# Give our non-root user access to /app +RUN chown -R disseminate:disseminate /app + +# Installing bash, mostly for debugging. +RUN apk add bash + +# Switching to non-root user. +USER disseminate + +# Copying the compiled project into our main image, ownership of the build is set to our aforementioned (non-root) user. +COPY --chown=$UID:$GID --from=compiled /tmp/build/ /app + +# Installing the dependencies. +RUN yarn install --production + +# Startup command +CMD ["npm", "run", "docker:prod:bootstrapper"] diff --git a/data.template/posts/about.md b/data.template/posts/about.md new file mode 100644 index 0000000..73d3fac --- /dev/null +++ b/data.template/posts/about.md @@ -0,0 +1,3 @@ +# About Me. + +Hello! diff --git a/data.template/posts/contact.md b/data.template/posts/contact.md new file mode 100644 index 0000000..e067a4f --- /dev/null +++ b/data.template/posts/contact.md @@ -0,0 +1,3 @@ +# Contact Information. + +Contact me! diff --git a/data.template/posts/welcome.md b/data.template/posts/welcome.md new file mode 100644 index 0000000..27c686c --- /dev/null +++ b/data.template/posts/welcome.md @@ -0,0 +1,13 @@ +# Welcome to Disseminate! + +Welcome, user! We are glad to have you on board! +To start, find the "posts" directory in the data folder you have created, or mounted using docker. +This is the same directory you put your config file in. + +Create a file named "hello.md", and start the file with: +``` +# [Your Title] +``` + +Now you can start writing blog posts! + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d555337 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +services: + disseminate: + build: + context: . + args: + UID: 1000 + GID: 1000 + volumes: + - ./data:/app/data + ports: + - 3024:3024 diff --git a/package.json b/package.json index 34ee94c..f9f8795 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,9 @@ "scripts":{ "docker:build": "bash scripts/docker_build.sh", "docker:test": "bash scripts/docker_test.sh", - "docker:test:bash": "bash scripts/docker_test_bash.sh", - "docker:prod:run": "/bin/sh /app/run.sh", + "docker:test:shell": "bash scripts/docker_test_bash.sh", + "docker:prod:bootstrapper": "/bin/bash /app/bootstrapper.sh", + "docker:prod:_runner": "/bin/bash /app/runner.sh", "dev:run": "ts-node -r tsconfig-paths/register src/index.ts" } } diff --git a/scripts/docker_bootstrapper.sh b/scripts/docker_bootstrapper.sh new file mode 100755 index 0000000..a042858 --- /dev/null +++ b/scripts/docker_bootstrapper.sh @@ -0,0 +1,25 @@ +cat << EOF + ____ ______________ __ + / __ \/ _/ ___/ ___// / docker edition + / / / // / \__ \\__ \/ / launching bootstrapper... + / /_/ // / ___/ /__/ /_/ running as $(whoami) +/_____/___//____/____(_) + +EOF +if [ -z "$(find data -mindepth 1 -maxdepth 1)" ]; then + echo '[bootstrapper] data directory is empty, copying template.' + cp -r data.template/* data/ + chown -R disseminate:disseminate data/ +fi + +# echo "[bootstrapper] checking permissions for data folder" +# permissions=$(ls -ld data) +# ldArr=(${permissions// / }) + +#if [[ ${ldArr[3]} != "node" ]]; then +# echo "[bootstrapper] data folder is owned by user ${ldArr[3]}, which is not node." +# echo "[bootstrapper] correcting permissions..." +# chown -R 1000:1000 data/ +#fi +echo "[bootstrapper] launching runner" +npm run docker:prod:_runner diff --git a/scripts/docker_build.sh b/scripts/docker_build.sh index 947a393..867dac4 100755 --- a/scripts/docker_build.sh +++ b/scripts/docker_build.sh @@ -1,4 +1,4 @@ # Disseminate Build Script # This script builds disseminate into a docker container, using the dockerfile provided in the repository. -docker build . -t disseminate:latest +docker build --build-arg UID=1000 --build-arg GID=1000 . -t disseminate:latest diff --git a/scripts/docker_run.sh b/scripts/docker_run.sh index 4bbef67..d77ba23 100755 --- a/scripts/docker_run.sh +++ b/scripts/docker_run.sh @@ -1,27 +1,14 @@ # I'm so bad at bash scripting -cat << EOF - ____ ______________ __ - / __ \/ _/ ___/ ___// / - / / / // / \__ \\__ \/ / - / /_/ // / ___/ /__/ /_/ -/_____/___//____/____(_) +#cat << EOF +# ____ ______________ __ +# / __ \/ _/ ___/ ___// / +# / / / // / \__ \\__ \/ / +# / /_/ // / ___/ /__/ /_/ +#/_____/___//____/____(_) +# +#EOF -EOF -if [ ! -d data ]; then - echo '-------------' - echo 'Data folder not found. Did you set up a volume?' - echo '-------------' - exit 1 -fi -if [ -z "$(find data -mindepth 1 -maxdepth 1)" ]; then - echo '-------------' - echo 'Data directory is empty, copying template.' - echo '-------------' - cp -r data.template/* data/ -fi - - -echo 'Starting...' +echo '[runner] starting...' node src/index.js -echo 'Exiting...' +echo '[runner] exited.' diff --git a/scripts/docker_test.sh b/scripts/docker_test.sh index 6aca363..0ec595c 100755 --- a/scripts/docker_test.sh +++ b/scripts/docker_test.sh @@ -1,5 +1,8 @@ # Disseminate docker test script - mkdir ignore cd ignore + docker run --rm -it -p 3024:3024 -v ./data:/app/data disseminate:latest + +cd .. +rm -R ignore diff --git a/scripts/docker_test_bash.sh b/scripts/docker_test_bash.sh index 917271d..1775428 100755 --- a/scripts/docker_test_bash.sh +++ b/scripts/docker_test_bash.sh @@ -2,5 +2,6 @@ mkdir ignore cd ignore -docker run --rm -it -p 3024:3024 -v ./data:/app/data disseminate:latest /bin/sh +docker run --rm -it -p 3024:3024 --user 1000:1000 -v ./data:/app/data disseminate:latest /bin/bash +cd .. rm ignore