-
Notifications
You must be signed in to change notification settings - Fork 1
/
Dockerfile
134 lines (101 loc) · 4.8 KB
/
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
FROM node:12.22.12-alpine as frontend
# Make build & post-install scripts behave as if we were in a CI environment (e.g. for logging verbosity purposes).
ARG CI=true
# Install front-end dependencies.
COPY package.json package-lock.json .babelrc webpack.config.js ./
RUN npm ci --no-optional --no-audit --progress=false
# Install operating system dependencies.
# npm needs this to sync directories.
RUN apk add --no-cache rsync
# Compile static files
COPY ./bc/static_src/ ./bc/static_src/
RUN npm run build:prod
# We use Debian images because they are considered more stable than the alpine
# ones becase they use a different C compiler. Debian images also come with
# all useful packages required for image manipulation out of the box. They
# however weight a lot, approx. up to 1.5GiB per built image.
FROM python:3.8-bullseye as backend
ARG POETRY_HOME=/opt/poetry
ARG POETRY_INSTALL_ARGS="--no-dev"
# IMPORTANT: Remember to review both of these when upgrading
ARG POETRY_VERSION=1.8.3
# Install dependencies in a virtualenv
ENV VIRTUAL_ENV=/venv
RUN useradd bc --create-home && mkdir /app $VIRTUAL_ENV && chown -R bc /app $VIRTUAL_ENV
WORKDIR /app
# Set default environment variables. They are used at build time and runtime.
# If you specify your own environment variables on Heroku or Dokku, they will
# override the ones set here. The ones below serve as sane defaults only.
# * PATH - Make sure that Poetry is on the PATH, along with our venv
# * PYTHONUNBUFFERED - This is useful so Python does not hold any messages
# from being output.
# https://docs.python.org/3.8/using/cmdline.html#envvar-PYTHONUNBUFFERED
# https://docs.python.org/3.8/using/cmdline.html#cmdoption-u
# * DJANGO_SETTINGS_MODULE - default settings used in the container.
# * PORT - default port used. Please match with EXPOSE so it works on Dokku.
# Heroku will ignore EXPOSE and only set PORT variable. PORT variable is
# read/used by Gunicorn.
# * WEB_CONCURRENCY - number of workers used by Gunicorn. The variable is
# read by Gunicorn.
# * GUNICORN_CMD_ARGS - additional arguments to be passed to Gunicorn. This
# variable is read by Gunicorn
ENV PATH=$VIRTUAL_ENV/bin:$PATH \
POETRY_INSTALL_ARGS=${POETRY_INSTALL_ARGS} \
PYTHONUNBUFFERED=1 \
DJANGO_SETTINGS_MODULE=bc.settings.production \
PORT=8000 \
WEB_CONCURRENCY=3 \
GUNICORN_CMD_ARGS="-c gunicorn-conf.py --max-requests 1200 --max-requests-jitter 50 --access-logfile - --timeout 25"
# Make $BUILD_ENV available at runtime
ARG BUILD_ENV
ENV BUILD_ENV=${BUILD_ENV}
# Port exposed by this container. Should default to the port used by your WSGI
# server (Gunicorn). This is read by Dokku only. Heroku will ignore this.
EXPOSE 8000
# Install poetry at the system level
RUN pip install --no-cache poetry==${POETRY_VERSION}
# Copy gunicorn config overrides.
COPY gunicorn-conf.py ./
COPY --chown=bc --from=frontend ./bc/static_compiled ./bc/static_compiled
WORKDIR /app
# Don't use the root user as it's an anti-pattern and Heroku does not run
# containers as root either.
# https://devcenter.heroku.com/articles/container-registry-and-runtime#dockerfile-commands-and-runtime
USER bc
# Install your app's Python requirements.
RUN python -m venv $VIRTUAL_ENV
COPY --chown=bc pyproject.toml poetry.lock ./
RUN pip install --no-cache --upgrade pip && poetry install ${POETRY_INSTALL_ARGS} --no-root --extras gunicorn && rm -rf $HOME/.cache
# Copy application code.
COPY --chown=bc . .
# Run poetry install again to install our project (so the the bc package is always importable)
RUN poetry install ${POETRY_INSTALL_ARGS}
# Collect static. This command will move static files from application
# directories and "static_compiled" folder to the main static directory that
# will be served by the WSGI server.
RUN SECRET_KEY=none django-admin collectstatic --noinput --clear
# Load shortcuts
COPY ./docker/bashrc.sh /home/bc/.bashrc
# Run the WSGI server. It reads GUNICORN_CMD_ARGS, PORT and WEB_CONCURRENCY
# environment variable hence we don't specify a lot options below.
CMD gunicorn bc.wsgi:application
# These steps won't be run on production
FROM backend as dev
# Swap user, so the following tasks can be run as root
USER root
# Update apt repositories
RUN apt-get update --yes --quiet
# Install `psql`, useful for `manage.py dbshell`
# `rsync` is used by mode to build the frontend.
RUN apt-get install -y postgresql-client rsync
# Restore user
USER bc
# Install nvm and node/npm
ARG NVM_VERSION=0.39.3
COPY --chown=bc .nvmrc ./
RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash \
&& bash --login -c "nvm install --no-progress && nvm alias default $(nvm run --silent --version)"
# Pull in the node modules for the frontend
COPY --chown=bc --from=frontend ./node_modules ./node_modules
# do nothing forever - exec commands elsewhere
CMD tail -f /dev/null