diff --git a/Dockerfile b/Dockerfile index f7e5c903bdf..856db13da6d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,7 +63,6 @@ RUN ve/bin/pip install --no-cache-dir gunicorn COPY --from=build-frontend /home/node/dist specifyweb/frontend/static/js COPY --chown=specify:specify specifyweb /opt/specify7/specifyweb COPY --chown=specify:specify manage.py /opt/specify7/ -COPY --chown=specify:specify docker-entrypoint.sh /opt/specify7/ COPY --chown=specify:specify Makefile /opt/specify7/ COPY --chown=specify:specify specifyweb.wsgi /opt/specify7/ @@ -124,8 +123,6 @@ ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 ENV DJANGO_SETTINGS_MODULE='settings' -ENTRYPOINT ["/opt/specify7/docker-entrypoint.sh"] - EXPOSE 8000 @@ -156,6 +153,8 @@ FROM run-common AS run RUN mv specifyweb.wsgi specifyweb_wsgi.py -CMD ["ve/bin/gunicorn", "-w", "3", "-b", "0.0.0.0:8000", "-t", "300", "specifyweb_wsgi"] +COPY --chown=specify:specify docker-entrypoint.sh /opt/specify7/ +ENTRYPOINT ["/opt/specify7/docker-entrypoint.sh"] +CMD ["sp7start"] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index c565f8b4752..7b60d5c3483 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,16 +1,84 @@ #!/bin/bash -set -e - -if [ "$1" = 've/bin/gunicorn' ] || [ "$1" = 've/bin/python' ]; then - echo "Updating static files in /volumes/static-files/." - rsync -a --delete specifyweb/frontend/static/ /volumes/static-files/frontend-static - cd /opt/specify7 - echo "Applying Django migrations." - set +e - # The following commands are prone to failing - # See https://github.com/specify/specify7/issues/789 and https://github.com/specify/docker-compositions/issues/7 - ve/bin/python manage.py migrate notifications - ve/bin/python manage.py migrate workbench - set -e -fi -exec "$@" + +# This entry point script implements a multi-mode image as described in +# https://aws.amazon.com/blogs/opensource/demystifying-entrypoint-cmd-docker/ +# +# It supports the following commands: +# +# sp7start -- This is the default CMD. When the container is invoked +# this way it checks if any Django migrations need to be +# performed. If so it refuses to start and issues instructions to +# do the migrations. Otherwise it performs a normal Specify 7 start +# up. +# +# sp7migrate -- When the container is invoked with this command it +# executes any outstanding migrations. +# +# sp7migrate-and-start -- This command executes any migrations and +# then starts Specify 7. It is less safe than doing the migrations +# independently but is convenient in testing scenarios. +# +# sp7worker -- This command starts the container in worker mode and +# is intended to simplify docker-compose.yml files. +# +# Any other command is executed as is. +# +# For the sp7start and sp7worker commands, any arguments are passed through to +# the underlying gunicorn or celery command, respectively. + + +set -euf -o pipefail + +sp7start () { + echo "Updating static files in /volumes/static-files/." + rsync -a --delete specifyweb/frontend/static/ /volumes/static-files/frontend-static + + echo "Starting Specify 7." + exec ve/bin/gunicorn -w 3 -b 0.0.0.0:8000 -t 300 specifyweb_wsgi "$@" +} + +sp7migrate () { + echo "Applying Django migrations." + ve/bin/python manage.py migrate notifications + ve/bin/python manage.py migrate workbench +} + +case "$1" in + "sp7start" ) + shift + + if (ve/bin/python manage.py showmigrations notifications workbench | grep -q '\[ \]'); then + printf "\n\nSpecify 7 cannot start because Django migrations need to be applied.\n\n" + printf "Apply the migrations by:\n" + printf "1. Stopping any process that could be accessing your database \"$DATABASE_NAME\".\n" + printf "2. Backing up the database \"$DATABASE_NAME\".\n" + printf "3. Applying the migrations by running \"docker-compose run --rm THIS-CONTAINER sp7migrate\".\n" + else + sp7start "$@" + fi + ;; + + "sp7migrate" ) + shift + + sp7migrate + ;; + + "sp7migrate-and-start" ) + shift + + sp7migrate + sp7start "$@" + ;; + + "sp7worker" ) + shift + + echo "Starting Specify 7 Worker." + exec ve/bin/celery -A specifyweb worker -l INFO --concurrency=1 "$@" + ;; + + *) + exec "$@" + ;; +esac