Fix missing custom PDF link
[wolnelektury.git] / Dockerfile
1 # Wolne Lektury images.
2 #
3 # Stages marked with ##### are build targets:
4 #   deps      dev image (docker-compose.yml, code mounted)
5 #   test      docker-compose.test.yml
6 #   prod      production app image (default, last stage)
7 #   nginx     production nginx with static files
8 #   postgres  Postgres with Polish dictionary
9 # Stages marked with ===== are intermediate.
10
11
12 # Global build arguments. Stages using UID/GID must redeclare them
13 # (bare `ARG UID`) to bring them into scope; the defaults are set here.
14
15 ARG PYTHON_IMAGE=python:3.10-trixie
16 ARG UID=8100
17 ARG GID=8100
18
19
20 ##########
21 #  deps  #############################################################
22 #
23 #  Base system and requirements.
24 #  Used directly as the dev image, with code mounted.
25 #
26 FROM ${PYTHON_IMAGE} AS deps
27
28 ARG UID
29 ARG GID
30
31 RUN     apt-get update && apt-get install -y \
32         git \
33         calibre \
34         texlive-xetex texlive-lang-polish \
35         texlive-extra-utils \
36         texlive-lang-greek \
37         texlive-lang-other \
38         texlive-luatex \
39         texlive-fonts-extra \
40         texlive-fonts-extra-links \
41         fonts-noto-core fonts-noto-extra
42
43
44 COPY requirements/requirements.txt requirements.txt
45
46 RUN --mount=type=cache,target=/root/.cache/pip \
47     pip install -r requirements.txt
48 RUN --mount=type=cache,target=/root/.cache/pip \
49     pip install \
50     psycopg2-binary \
51     django-debug-toolbar==3.2.2
52
53 RUN addgroup --gid $GID app && \
54     adduser --gid $GID --home /app --uid $UID app
55
56
57 # fonts
58 RUN cp -a /usr/local/lib/python*/site-packages/librarian/fonts /usr/share/fonts
59 RUN fc-cache
60
61 USER app
62
63 WORKDIR /app/src
64
65 RUN mkdir /app/.ipython
66
67
68 #=======#
69 #  app  #=============================================================
70 #
71 #  Code and production requirements. Not production yet: needs
72 #  staticfiles.json manifest from static-builder.
73 #
74 FROM deps AS app
75
76 USER root
77
78 RUN --mount=type=cache,target=/root/.cache/pip \
79     pip install gunicorn
80
81 USER app
82
83 COPY src /app/src
84
85
86 #==================#
87 #  static-builder  #==================================================
88 #
89 #  Static files are collected here. Statics are then copied into
90 #  the nginx image, and staticfiles.json manifest is copied back
91 #  into the test and prod images.
92 #
93 FROM app AS static-builder
94
95 RUN python manage.py collectstatic --noinput
96
97
98 ###########
99 #  nginx  ############################################################
100 #
101 #  Static files for production nginx. Config is mounted.
102 #
103 FROM nginx:alpine AS nginx
104
105 ARG UID
106 ARG GID
107
108 # COPY nginx.conf conf.d/...
109
110 RUN addgroup -g $GID app && addgroup nginx app
111 COPY --from=static-builder /app/var/static /app/var/static
112
113
114 #===============#
115 #  polish-dict  #=====================================================
116 #
117 #  Polish hunspell dictionary without diacritics, to allow
118 #  full text search without diacritics.
119 #
120 FROM ${PYTHON_IMAGE} AS polish-dict
121
122 RUN apt-get update \
123  && apt-get install -y --no-install-recommends hunspell-pl \
124  && rm -rf /var/lib/apt/lists/*
125
126 COPY scripts/fold_hunspell.py /usr/local/bin/fold_hunspell.py
127
128 RUN set -eu; \
129     mkdir /out; cd /tmp; \
130     enc="$(sed -n 's/^SET[[:space:]]*//p' /usr/share/hunspell/pl_PL.aff | tr -d '\r')"; \
131     iconv -f "${enc:-UTF-8}" -t UTF-8 /usr/share/hunspell/pl_PL.dic > pl.dict; \
132     iconv -f "${enc:-UTF-8}" -t UTF-8 /usr/share/hunspell/pl_PL.aff > pl.affix; \
133     python3 /usr/local/bin/fold_hunspell.py pl.dict pl.affix \
134         /out/polish.dict /out/polish.affix; \
135     dpkg-query -W -f='hunspell-pl ${Version}\n' hunspell-pl > /out/polish.version
136
137
138 ##############
139 #  postgres  #########################################################
140 #
141 #  Postgres with the dictionary from polish-dict.
142 #
143 FROM postgres:18 AS postgres
144
145 COPY --from=polish-dict /out/ /tmp/polish-dict/
146 RUN mv /tmp/polish-dict/* "/usr/share/postgresql/$PG_MAJOR/tsearch_data/" \
147  && rmdir /tmp/polish-dict
148
149 COPY scripts/postgres-polish.sql /docker-entrypoint-initdb.d/10-postgres-polish.sql
150
151
152 ##########
153 #  test  #############################################################
154 #
155 #  Production image plus test requirements. Defined before `prod`,
156 #  so that `prod` stays the default (last) stage.
157 #
158 FROM app AS test
159
160 USER root
161 COPY requirements/requirements-test.txt /tmp/
162 RUN --mount=type=cache,target=/root/.cache/pip \
163     pip install -r /tmp/requirements-test.txt
164 USER app
165 RUN mkdir -p /app/var/counters
166 COPY --from=static-builder /app/var/static/staticfiles.json /app/var/static/staticfiles.json
167 CMD ["./manage.py", "test"]
168
169
170 ##########
171 #  prod  #############################################################
172 #
173 #  Production image: app + staticfiles.json manifest.
174 #
175 FROM app AS prod
176
177 COPY --from=static-builder /app/var/static/staticfiles.json /app/var/static/staticfiles.json