/
Dockerfile
207 lines (170 loc) · 6.82 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
ARG RUBY_VERSION="3.2.2"
ARG NODE_VERSION="20.9.0"
ARG BUNDLER_VERSION="2.4.7"
ARG DEBIAN_FRONTEND=noninteractive
# -------------------------------------
# rubygems (private)
# -------------------------------------
FROM ruby:${RUBY_VERSION}-bullseye as rubygems
ENV BUNDLE_JOBS=8
ENV BUNDLE_RETRY=3
ENV BUNDLE_WITHOUT="development:test"
WORKDIR /app
RUN gem install bundler --version "$BUNDLER_VERSION" --no-document
COPY Gemfile Gemfile.modules Gemfile.lock ./
COPY modules ./modules
RUN bundle install
# -------------------------------------
# nodejs (private)
# -------------------------------------
# Using docker image for node so that multi-arch is automatically taken care of
FROM node:${NODE_VERSION} as nodejs
WORKDIR /app
COPY package.json ./
COPY frontend/package.json frontend/package-lock.json frontend/.npmrc ./frontend/
RUN JOBS=8 npm install
# -------------------------------------
# assets (private)
# -------------------------------------
FROM rubygems as assets
COPY --from=nodejs /usr/local/bin/node /usr/local/bin/node
COPY --from=nodejs /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=nodejs /usr/local/include/node /usr/local/include/node
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
WORKDIR /app
COPY --from=nodejs /app/node_modules ./node_modules
COPY --from=nodejs /app/frontend/node_modules ./frontend/node_modules
COPY Rakefile .
COPY bin ./bin
COPY app ./app
COPY config ./config
COPY config/database.production.yml ./config/database.yml
COPY lib ./lib
COPY lib_static ./lib_static
COPY frontend ./frontend
COPY modules ./modules
COPY vendor ./vendor
COPY lookbook ./lookbook
RUN --mount=type=cache,target=/app/frontend/.angular/cache,uid=1000,gid=1000 \
SECRET_KEY_BASE=1 RAILS_ENV=production DATABASE_URL=nulldb://db \
bin/rails openproject:plugins:register_frontend assets:precompile
# -------------------------------------
# base (private)
# -------------------------------------
FROM ruby:${RUBY_VERSION}-slim-bullseye as base
LABEL maintainer="operations@openproject.com"
# SYSTEM
ENV APP_USER=app
ENV APP_PATH=/app
ENV APP_DATA_PATH=/var/openproject/assets
ENV PGVERSION="13"
ENV CURRENT_PGVERSION="13"
ENV NEXT_PGVERSION="15"
ENV PGBIN="/usr/lib/postgresql/$PGVERSION/bin"
ENV BUNDLE_WITHOUT="development:test"
# RAILS
# Set a default key base, ensure to provide a secure value in production environments!
ENV SECRET_KEY_BASE=OVERWRITE_ME
ENV RAILS_ENV=production
ENV RAILS_LOG_TO_STDOUT=1
ENV RAILS_SERVE_STATIC_FILES=1
# OPENPROJECT
# Valid values are: standard,bim
ENV OPENPROJECT_EDITION=standard
ENV OPENPROJECT_INSTALLATION__TYPE=docker
ENV OPENPROJECT_ATTACHMENTS__STORAGE__PATH=$APP_DATA_PATH/files
ENV OPENPROJECT_RAILS__CACHE__STORE=file_store
RUN useradd -d /home/$APP_USER -m $APP_USER
RUN mkdir -p $APP_PATH && chown $APP_USER:$APP_USER $APP_PATH
RUN mkdir -p $APP_DATA_PATH && chown $APP_USER:$APP_USER $APP_DATA_PATH && chmod g+rwx $APP_DATA_PATH
WORKDIR $APP_PATH
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update -qq \
&& apt-get install -yq --no-install-recommends \
file \
curl \
gnupg2 \
&& curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& echo 'deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main' > /etc/apt/sources.list.d/pgdg.list \
&& apt-get update -qq \
&& apt-get install -yq --no-install-recommends \
libpq5 \
postgresql-client-$CURRENT_PGVERSION \
postgresql-client-$NEXT_PGVERSION \
libffi7 \
unrtf tesseract-ocr poppler-utils catdoc imagemagick \
&& apt-get purge -y curl gnupg2 \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& truncate -s 0 /var/log/*log
# -------------------------------------
# slim (public)
# -------------------------------------
FROM base as slim
COPY --chown=$APP_USER:$APP_USER --from=rubygems /usr/local/bundle /usr/local/bundle
COPY --chown=$APP_USER:$APP_USER --from=assets /app/public/assets /app/public/assets
COPY --chown=$APP_USER:$APP_USER --from=assets /app/config/frontend_assets.manifest.json /app/config/frontend_assets.manifest.json
COPY --chown=$APP_USER:$APP_USER . .
# We need this so puma is allowed to create the tmp/pids folder and
# temporary upload files when running with a uid other than 1000 (app)
# but with an allowed supplemental group (1000).
RUN tmp_path=$APP_PATH/tmp; (mkdir -p $tmp_path || true) && chown $APP_USER:$APP_USER $tmp_path && chmod g+rw $tmp_path
USER $APP_USER
RUN ln -s $APP_PATH/docker/prod/setup/.irbrc /home/$APP_USER/
EXPOSE 8080
CMD ["./docker/prod/web"]
VOLUME ["$APP_DATA_PATH"]
# -------------------------------------
# all-in-one (public)
# -------------------------------------
FROM base as all-in-one
ARG DEBIAN_FRONTEND
ARG NODE_VERSION
ARG BUNDLER_VERSION
# Allow platform-specific additions. Valid values are: on-prem,saas,bahn
ARG PLATFORM=on-prem
# Use OAuth token in case private gems need to be fetched
ARG GITHUB_OAUTH_TOKEN
ARG BIM_SUPPORT=true
ARG GOSU_VERSION="1.16"
ARG OPENPROJECT_ANGULAR_UGLIFY=true
ENV OPENPROJECT_RAILS__CACHE__STORE=memcache
ENV DATABASE_URL=postgres://openproject:openproject@127.0.0.1/openproject
ENV PGDATA=/var/openproject/pgdata
ENV PGBIN="/usr/lib/postgresql/$PGVERSION/bin"
COPY docker/prod/setup ./docker/prod/setup
RUN ./docker/prod/setup/preinstall.sh
RUN dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
# set irb default config for app (docker run -it ...) and root (docker exec -it ...) users
RUN ln -s /app/docker/prod/setup/.irbrc /home/$APP_USER/
RUN ln -s /app/docker/prod/setup/.irbrc /root/
COPY Gemfile ./Gemfile
COPY Gemfile.* ./
COPY modules ./modules
COPY vendor ./vendor
# some gemspec files of plugins require files in there, notably OpenProject::Version
COPY lib ./lib
RUN \
bundle config set --local path 'vendor/bundle' && \
bundle config set --local without 'test development' && \
bundle install --quiet --no-cache --jobs=8 --retry=3 && \
bundle config set deployment 'true' && \
cp Gemfile.lock Gemfile.lock.bak && \
rm -rf vendor/bundle/ruby/*/cache && \
rm -rf vendor/bundle/ruby/*/gems/*/spec && \
rm -rf vendor/bundle/ruby/*/gems/*/test
# Finally, copy over the whole thing
COPY . .
# Copy lock file again as the updated version was overriden by COPY just now
RUN cp Gemfile.lock.bak Gemfile.lock && rm Gemfile.lock.bak
RUN ./docker/prod/setup/postinstall.sh
# Expose ports for apache and postgres
EXPOSE 80 5432
# Expose the postgres data directory and OpenProject data directory as volumes
VOLUME ["$PGDATA", "$APP_DATA_PATH"]
# Set a custom entrypoint to allow for privilege dropping and one-off commands
ENTRYPOINT ["./docker/prod/entrypoint.sh"]
# Set default command to launch the all-in-one configuration supervised by supervisord
CMD ["./docker/prod/supervisord"]