diff --git a/.dockerignore b/.dockerignore index c8965b40..89c8656a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -22,4 +22,16 @@ **/obj **/secrets.dev.yaml **/values.dev.yaml -README.md +**/.github +docs +profile +tests +**/LICENSE +**/README.md +**/PACKAGE.txt +**/.pyup.yml +**/app.json +**/deploy-stackscript.sh +**/package.json +**/Procfile +**/publish-docker.sh diff --git a/Dockerfile b/Dockerfile index 2046082c..9772731e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,51 @@ +# Based on python image which itself is based on debian image +# https://hub.docker.com/_/python +# https://hub.docker.com/_/debian FROM python:3.9-slim -# Install compiler -RUN apt-get update && apt-get install gcc -y && apt-get clean - -# Not needed for production -#RUN apt-get install -y nodejs npm -# Install node requirements (after WORKDIR) -#RUN npm install - -EXPOSE 5000 +# Maintainer information +LABEL maintainer="Dribdat " +# Environment # Keeps Python from generating .pyc files in the container ENV PYTHONDONTWRITEBYTECODE=1 - # Turns off buffering for easier container logging ENV PYTHONUNBUFFERED=1 -# Install pip requirements +# Copy pip requirements COPY requirements.txt . COPY requirements/* requirements/ -RUN python -m pip install --upgrade pip -RUN python -m pip install -r requirements.txt - -# Copy dribdat app -WORKDIR /app +# Copy app files (please see dockerignore) COPY . /app -# Creates a non-root user with an explicit UID and adds permission to access the /app folder -# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers -RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app +# Run commands +RUN set -x \ + && mkdir /docker-entrypoint.d \ + && mv /app/image/docker-entrypoint.d/* /docker-entrypoint.d/ \ + && mv /app/image/docker-entrypoint.sh /docker-entrypoint.sh \ + && chmod +x /docker-entrypoint.sh \ + && rm -rf /app/image \ + # Creates a non-root user with an explicit UID and adds permission to access the /app folder + && adduser --uid 5678 --disabled-password --gecos "" appuser \ + && chown -R appuser /app \ + && chown -R appuser /docker-entrypoint.d \ + && chown appuser /docker-entrypoint.sh \ + # Install compiler (used by some pip packages) + && apt-get update \ + && apt-get install gcc -y \ + && apt-get clean \ + # Install requirements + && python -m pip install --upgrade pip \ + && python -m pip install -r requirements.txt \ + # Clean up after build + && apt-get purge --auto-remove -y + +WORKDIR /app USER appuser -# Run release commands -RUN ./release.sh +ENTRYPOINT ["/docker-entrypoint.sh"] +EXPOSE 5000 +CMD ["/usr/local/bin/gunicorn","--config=gunicorn.conf.py","patched:init_app()"] + + -# During debugging, this entry point will be overridden. For more information, -# please refer to https://aka.ms/vscode-docker-python-debug -CMD gunicorn --config=gunicorn.conf.py patched:init_app\(\) diff --git a/force-migrate.sh b/force-migrate.sh index f6fbf64d..c17c0a00 100755 --- a/force-migrate.sh +++ b/force-migrate.sh @@ -5,9 +5,9 @@ if [ "$1" = "psql" ]; then echo "Force migrating database" rm -rf migrations/ psql -c "DROP TABLE alembic_version;" $DATABASE_URL - python manage.py db init 2>&1 >/dev/null - python manage.py db migrate - python manage.py db upgrade + python "${APPDIR:-.}/manage.py" db init 2>&1 >/dev/null + python "${APPDIR:-.}/manage.py" db migrate + python "${APPDIR:-.}/manage.py" db upgrade echo "Upgrade complete, 10 second cooldown" sleep 10 @@ -19,13 +19,13 @@ elif [ "$1" = "heroku" ]; then echo "Migrating Heroku DB on $2 in 5 seconds - Ctrl-C to abort." sleep 5s heroku pg:psql -a $2 -c "drop table alembic_version" - heroku run -a $2 "python manage.py db init && python manage.py db migrate && python manage.py db upgrade" + heroku run -a $2 "python ${APPDIR:-.}/manage.py db init && python ${APPDIR:-.}/manage.py db migrate && python ${APPDIR:-.}/manage.py db upgrade" elif [ "$1" = "local" ]; then echo "Resetting local SQLite DB (dev.db)" - rm -rf dev.db - python manage.py db migrate - python manage.py db upgrade + rm -rf "${APPDIR:-.}/dev.db" + python "${APPDIR:-.}/manage.py" db migrate + python "${APPDIR:-.}/manage.py" db upgrade else echo "Use this script with the following arguments to refresh the DB schema:" diff --git a/image/docker-entrypoint.d/10-migrate.sh b/image/docker-entrypoint.d/10-migrate.sh new file mode 100755 index 00000000..09e4c6bb --- /dev/null +++ b/image/docker-entrypoint.d/10-migrate.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +APPDIR=/app /app/release.sh \ No newline at end of file diff --git a/image/docker-entrypoint.sh b/image/docker-entrypoint.sh new file mode 100644 index 00000000..0e59043e --- /dev/null +++ b/image/docker-entrypoint.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +set -e + +log() { + if [ -z "${DRIBDAT_ENTRYPOINT_NO_LOGS:-}" ]; then + echo "$@" + fi +} + +if [ -z "${DRIBDAT_ENTRYPOINT_SKIP:-}" ]; then + if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + log "$0: /docker-entrypoint.d/ not empty, processing it" + find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do + case "$f" in + *.envsh) + if [ -x "$f" ]; then + log "$0: Sourcing $f"; + . "$f" + else + log "$0: Ignoring $f, executable bit not set"; + fi + ;; + *.sh) + if [ -x "$f" ]; then + log "$0: Executing $f"; + "$f" + else + log "$0: Ignoring $f, executable bit not set"; + fi + ;; + *) log "$0: Ignoring $f";; + esac + done + else + log "$0: Nothing found in /docker-entrypoint.d/, skipping" + fi +fi + +echo "$@" +echo "$PATH" +type gunicorn + +# execute the command passed to the container +exec "$@" \ No newline at end of file diff --git a/release.sh b/release.sh index afa58897..3de801f2 100755 --- a/release.sh +++ b/release.sh @@ -1,17 +1,19 @@ #!/bin/bash # Release script +# set APPDIR if running from a different directory, e.g. in container + if [ "$FORCE_MIGRATE" ]; then - ./force-migrate.sh psql + "${APPDIR:-.}/force-migrate.sh" psql else # Silent upgrade - python manage.py db upgrade 2>&1 >/dev/null + python "${APPDIR:-.}/manage.py" db upgrade 2>&1 >/dev/null echo "Warning! Your database may be out of sync due to a forced upgrade." fi # Compress assets -python -m whitenoise.compress dribdat/static/js -python -m whitenoise.compress dribdat/static/css -python -m whitenoise.compress dribdat/static/img -python -m whitenoise.compress dribdat/static/public +python -m whitenoise.compress "${APPDIR:-.}/dribdat/static/js" +python -m whitenoise.compress "${APPDIR:-.}/dribdat/static/css" +python -m whitenoise.compress "${APPDIR:-.}/dribdat/static/img" +python -m whitenoise.compress "${APPDIR:-.}/dribdat/static/public"