forked from onetimesecret/onetimesecret
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDockerfile
251 lines (221 loc) · 7.28 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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# syntax=docker/dockerfile:1.10
# check=error=true
##
# ONETIME SECRET - DOCKER IMAGE - 2024-10-10
#
# For detailed instructions on building, running, and deploying this Docker image,
# please refer to our comprehensive Docker guide:
#
# docs/DOCKER.md
#
# This guide includes information on:
# - Quick start instructions
# - Configuration options
# - Production deployment considerations
# - Updating the Docker image
# - Using specific version tags
#
# For more detailed configuration options, you can also refer to the README.md file.
#
# GETTING STARTED:
#
# To build and use this image, you need to copy the example
# configuration files into place:
#
# $ cp --preserve --no-clobber ./etc/config.example.yaml ./etc/config
# $ cp --preserve --no-clobber .env.example .env
#
# The default values work as-is but it's a good practice to have
# a look and customize as you like (particularly the main secret
# `SECRET` and redis password in `REDIS_URL`).
#
# BUILDING:
#
# $ docker build -t onetimesecret .
#
# For multi-platform builds:
#
# $ docker buildx build --platform=linux/amd64,linux/arm64 . -t onetimesecret
#
# RUNNING:
#
# First, start a Redis server (version 5+) with persistence enabled:
#
# $ docker run -p 6379:6379 -d redis:bookworm
#
# Then set essential environment variables:
#
# $ export HOST=localhost:3000
# $ export SSL=false
# $ export COLONEL=admin@example.com
# $ export REDIS_URL=redis://host.docker.internal:6379/0
# $ export RACK_ENV=production
#
# Run the OnetimeSecret container:
#
# $ docker run -p 3000:3000 -d --name onetimesecret \
# -e REDIS_URL=$REDIS_URL \
# -e COLONEL=$COLONEL \
# -e HOST=$HOST \
# -e SSL=$SSL \
# -e RACK_ENV=$RACK_ENV \
# onetimesecret
#
# It will be accessible on http://localhost:3000.
#
# PRODUCTION DEPLOYMENT:
#
# When deploying to production, protect your Redis instance with
# authentication and enable persistence. Also, change the secret and
# specify the domain it will be deployed on. For example:
#
# $ export HOST=example.com
# $ export SSL=true
# $ export COLONEL=admin@example.com
# $ export REDIS_URL=redis://username:password@hostname:6379/0
# $ export RACK_ENV=production
#
# $ docker run -p 3000:3000 -d --name onetimesecret \
# -e REDIS_URL=$REDIS_URL \
# -e COLONEL=$COLONEL \
# -e HOST=$HOST \
# -e SSL=$SSL \
# -e RACK_ENV=$RACK_ENV \
# onetimesecret
#
# For more detailed configuration options, refer to the README.md file.
##
# BUILDER LAYER
#
# Installs system packages, updates RubyGems, and prepares the
# application's package management dependencies using a Debian
# Ruby 3.3 base image.
#
ARG CODE_ROOT=/app
ARG ONETIME_HOME=/opt/onetime
ARG VERSION=0.0.0
FROM docker.io/library/ruby:3.3-slim-bookworm AS base
# Limit to packages needed for the system itself
ARG PACKAGES="build-essential rsync netcat-openbsd"
# Fast fail on errors while installing system packages
RUN set -eux \
&& apt-get update \
&& apt-get install -y $PACKAGES \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copy Node.js and npm from the official image
COPY --from=docker.io/library/node:22 /usr/local/bin/node /usr/local/bin/
COPY --from=docker.io/library/node:22 /usr/local/lib/node_modules /usr/local/lib/node_modules
# Create necessary symlinks
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
&& ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
# Verify Node.js and npm installation
RUN node --version && npm --version
# Install necessary tools
RUN set -eux \
&& gem install bundler \
&& npm install -g pnpm
##
# DEPENDENCIES LAYER
#
# Sets up the necessary directories, installs additional
# system packages for userland, and installs the application's
# dependencies using the Base Layer as a starting point.
#
FROM base AS app_deps
ARG CODE_ROOT
ARG ONETIME_HOME
ARG VERSION
# Create the directories that we need in the following image
RUN set -eux \
&& echo "Creating directories" \
&& mkdir -p $CODE_ROOT $ONETIME_HOME/{log,tmp}
WORKDIR $CODE_ROOT
ENV NODE_PATH=$CODE_ROOT/node_modules
# Install the dependencies into the environment image
COPY Gemfile Gemfile.lock ./
COPY package.json pnpm-lock.yaml ./
RUN set -eux \
&& bundle config set --local without 'development test' \
&& bundle update --bundler \
&& bundle install \
&& pnpm install --frozen-lockfile
##
# BUILD LAYER
#
FROM app_deps AS build
ARG CODE_ROOT
ARG VERSION
WORKDIR $CODE_ROOT
COPY public $CODE_ROOT/public
COPY templates $CODE_ROOT/templates
COPY src $CODE_ROOT/src
COPY package.json pnpm-lock.yaml tsconfig.json vite.config.ts postcss.config.mjs tailwind.config.ts eslint.config.mjs ./
# Remove pnpm after use
RUN set -eux \
&& pnpm run type-check \
&& pnpm run build-only \
&& pnpm prune --prod \
&& rm -rf node_modules \
&& npm uninstall -g pnpm \
&& touch .commit_hash.txt # avoid ignorable error later on
##
# APPLICATION LAYER (FINAL)
#
FROM ruby:3.3-slim-bookworm AS final
ARG CODE_ROOT
ARG VERSION
WORKDIR $CODE_ROOT
## Copy only necessary files from previous stages
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build $CODE_ROOT/public $CODE_ROOT/public
COPY --from=build $CODE_ROOT/templates $CODE_ROOT/templates
COPY --from=build $CODE_ROOT/src $CODE_ROOT/src
COPY --from=build $CODE_ROOT/.commit_hash.txt $CODE_ROOT/
COPY bin $CODE_ROOT/bin
COPY etc $CODE_ROOT/etc
COPY lib $CODE_ROOT/lib
COPY migrate $CODE_ROOT/migrate
COPY package.json config.ru Gemfile Gemfile.lock $CODE_ROOT/
LABEL Name=onetimesecret Version=$VERSION
LABEL maintainer="Onetime Secret <docker-maint@onetimesecret.com>"
LABEL org.opencontainers.image.description="Onetime Secret is a web application to share sensitive information securely and temporarily. This image contains the application and its dependencies."
# See: https://fly.io/docs/rails/cookbooks/deploy/
ENV RUBY_YJIT_ENABLE=1
# Explicitly setting the Rack environment to production directs
# the application to use the pre-built JS/CSS assets in the
# "public/web/dist" directory. In dev mode, the application
# expects a vite server to be running on port 5173 and will
# attempt to connect to that server for each request.
#
# $ pnpm run dev
# VITE v5.3.4 ready in 38 ms
#
# ➜ Local: http://localhost:5173/dist/
# ➜ Network: use --host to expose
# ➜ press h + enter to show help
#
ENV RACK_ENV=production
WORKDIR $CODE_ROOT
# Copy the default config file into place if it doesn't
# already exist. If it does exist, nothing happens. For
# example, if the config file has been previously copied
# (and modified) the "--no-clobber" argument prevents
# those changes from being overwritten.
RUN set -eux \
&& cp --preserve --no-clobber etc/config.example.yaml etc/config.yaml
# About the interplay between the Dockerfile CMD, ENTRYPOINT,
# and the Docker Compose command settings:
#
# 1. The CMD instruction in the Dockerfile sets the default command to
# be executed when the container is started.
#
# 2. The command setting in the Docker Compose configuration overrides
# the CMD instruction in the Dockerfile.
#
# 3. Using the CMD instruction in the Dockerfile provides a fallback
# command, which can be useful if no specific command is set in the
# Docker Compose configuration.
# Rack app
EXPOSE 3000
CMD ["bin/entrypoint.sh"]