monkrb 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +166 -0
- data/README.md +7 -6
- data/exe/monk +3 -181
- data/lib/monk/assets.rb +39 -9
- data/lib/monk/auth/errors.rb +3 -0
- data/lib/monk/auth/helpers.rb +11 -0
- data/lib/monk/auth/send_login_link.rb +36 -0
- data/lib/monk/auth.rb +34 -5
- data/lib/monk/base.rb +20 -0
- data/lib/monk/bin.rb +107 -0
- data/lib/monk/cli.rb +277 -0
- data/lib/monk/context.rb +17 -0
- data/lib/monk/errors.rb +0 -6
- data/lib/monk/generator/definition.rb +153 -0
- data/lib/monk/generator/result.rb +279 -0
- data/lib/monk/generator/run.rb +449 -0
- data/lib/monk/generator.rb +48 -0
- data/lib/monk/generators/auth.rb +29 -0
- data/lib/monk/generators/base.rb +19 -0
- data/lib/monk/generators/jobs.rb +21 -0
- data/lib/monk/generators/live.rb +26 -0
- data/lib/monk/generators/mail.rb +24 -0
- data/lib/monk/generators/postgres.rb +23 -0
- data/lib/monk/generators/redis.rb +20 -0
- data/lib/monk/generators/websocket.rb +24 -0
- data/lib/monk/generators.rb +7 -0
- data/lib/monk/jobs/adapters/pg.rb +3 -1
- data/lib/monk/jobs.rb +7 -0
- data/lib/monk/live/helpers.rb +13 -0
- data/lib/monk/live/policy.rb +39 -4
- data/lib/monk/live/session.rb +7 -0
- data/lib/monk/live.rb +17 -4
- data/lib/monk/log.rb +10 -1
- data/lib/monk/mail/deliver_later.rb +54 -0
- data/lib/monk/mail/later.rb +3 -51
- data/lib/monk/mail.rb +4 -0
- data/lib/monk/persistence/errors.rb +32 -0
- data/lib/monk/persistence/pg.rb +92 -1
- data/lib/monk/persistence/pool.rb +513 -0
- data/lib/monk/persistence.rb +196 -7
- data/lib/monk/templates/auth/agents.md +29 -0
- data/lib/monk/templates/auth/app/mailers/{app_mailer.rb → auth_mailer.rb} +5 -5
- data/lib/monk/templates/auth/app/routes/auth.rb +48 -0
- data/lib/monk/templates/auth/app/views/auth/login.erb +25 -0
- data/lib/monk/templates/auth/config/auth.rb +14 -8
- data/lib/monk/templates/auth/setup.md +37 -0
- data/lib/monk/templates/auth/test/auth_test.rb +17 -0
- data/lib/monk/templates/base/CLAUDE.md +1 -0
- data/lib/monk/templates/base/Dockerfile +4 -3
- data/lib/monk/templates/base/Gemfile +7 -2
- data/lib/monk/templates/base/Rakefile +8 -0
- data/lib/monk/templates/base/agents.md +41 -0
- data/lib/monk/templates/base/app/app.rb +5 -0
- data/lib/monk/templates/base/app/routes/.keep +0 -0
- data/lib/monk/templates/base/app/views/index.erb +1 -1
- data/lib/monk/templates/base/app/views/layouts/app.erb +2 -0
- data/lib/monk/templates/base/config/load.rb +8 -0
- data/lib/monk/templates/base/config/settings.rb +4 -5
- data/lib/monk/templates/base/setup.md +22 -0
- data/lib/monk/templates/base/test/app_test.rb +12 -0
- data/lib/monk/templates/base/test/test_helper.rb +18 -0
- data/lib/monk/templates/jobs/agents.md +25 -0
- data/lib/monk/templates/jobs/app/routes/jobs.rb +9 -0
- data/lib/monk/templates/jobs/bin/jobs +19 -13
- data/lib/monk/templates/jobs/setup.md +30 -0
- data/lib/monk/templates/jobs/test/jobs_test.rb +16 -0
- data/lib/monk/templates/live/agents.md +25 -0
- data/lib/monk/templates/live/app/broadcasts/greeting.rb +13 -0
- data/lib/monk/templates/live/app/routes/demo_live.rb +21 -0
- data/lib/monk/templates/live/app/routes/live.rb +10 -0
- data/lib/monk/templates/live/app/views/demo/live.erb +18 -0
- data/lib/monk/templates/live/app/views/live/_greeting.erb +1 -0
- data/lib/monk/templates/live/config/live.rb +30 -32
- data/lib/monk/templates/live/config/live_without_demo.rb +38 -0
- data/lib/monk/templates/live/setup.md +39 -0
- data/lib/monk/templates/live/test/live_test.rb +22 -0
- data/lib/monk/templates/mail/agents.md +22 -0
- data/lib/monk/templates/mail/app/mailers/app_mailer.rb +14 -0
- data/lib/monk/templates/mail/app/routes/mail.rb +12 -0
- data/lib/monk/templates/mail/app/views/mail/welcome.erb +1 -0
- data/lib/monk/templates/mail/config/mail.rb +4 -4
- data/lib/monk/templates/mail/setup.md +32 -0
- data/lib/monk/templates/mail/test/mail_test.rb +13 -0
- data/lib/monk/templates/postgres/agents.md +25 -0
- data/lib/monk/templates/postgres/app/routes/postgres.rb +22 -0
- data/lib/monk/templates/postgres/bin/console +3 -1
- data/lib/monk/templates/postgres/bin/migrate +23 -17
- data/lib/monk/templates/postgres/bin/setup_db +11 -5
- data/lib/monk/templates/postgres/config/persistence.rb +1 -0
- data/lib/monk/templates/postgres/db/migrate/.keep +0 -0
- data/lib/monk/templates/postgres/setup.md +38 -0
- data/lib/monk/templates/postgres/test/persistence_test.rb +11 -0
- data/lib/monk/templates/redis/agents.md +18 -0
- data/lib/monk/templates/redis/app/routes/redis.rb +15 -0
- data/lib/monk/templates/redis/config/redis.rb +13 -0
- data/lib/monk/templates/redis/setup.md +20 -0
- data/lib/monk/templates/redis/test/redis_test.rb +12 -0
- data/lib/monk/templates/websocket/agents.md +25 -0
- data/lib/monk/templates/websocket/app/sockets/chat.rb +18 -0
- data/lib/monk/templates/websocket/bin/websocket_server +58 -0
- data/lib/monk/templates/websocket/config/websocket_postgres.rb +24 -0
- data/lib/monk/templates/websocket/config/websocket_redis.rb +21 -0
- data/lib/monk/templates/websocket/setup.md +51 -0
- data/lib/monk/templates/websocket/test/websocket_test.rb +21 -0
- data/lib/monk/version.rb +1 -1
- data/lib/monk/websocket/connection.rb +25 -6
- data/lib/monk/websocket/listeners.rb +24 -0
- data/lib/monk/websocket/pg_fanout.rb +143 -20
- data/lib/monk/websocket/redis_fanout.rb +78 -29
- data/lib/monk/websocket/registry.rb +24 -0
- data/lib/monk/websocket/server.rb +57 -16
- data/lib/monk/websocket.rb +2 -0
- data/lib/monk.rb +10 -0
- metadata +83 -14
- data/lib/monk/scaffold.rb +0 -1061
- data/lib/monk/templates/base/bin/websocket_server +0 -68
- data/lib/monk/templates/jobs/app/jobs/send_login_link.rb +0 -28
- data/lib/monk/templates/live/app/app.rb +0 -22
- data/lib/monk/templates/live/app/views/index.erb +0 -18
- data/lib/monk/templates/live/bin/websocket_server +0 -42
- data/lib/monk/templates/live/config/live_pg.rb +0 -60
- data/lib/monk/templates/mail/Gemfile.extra +0 -1
- data/lib/monk/templates/postgres/Dockerfile +0 -32
- data/lib/monk/templates/postgres/Gemfile.extra +0 -2
- data/lib/monk/templates/redis/Gemfile.extra +0 -1
- /data/lib/monk/templates/live/app/views/{live → demo}/_hits.erb +0 -0
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
require "bundler/setup"
|
|
3
|
-
require_relative "../config/settings"
|
|
4
|
-
|
|
5
|
-
# config/auth.rb only exists if this app was scaffolded with --auth -- a
|
|
6
|
-
# missing file is a harmless no-op, the same way config/settings.rb treats
|
|
7
|
-
# a missing dotenv gem. Present or not, it's what decides whether this
|
|
8
|
-
# process authenticates connections below.
|
|
9
|
-
begin
|
|
10
|
-
require_relative "../config/auth"
|
|
11
|
-
rescue LoadError
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
require "monk/websocket"
|
|
15
|
-
|
|
16
|
-
# A single broadcast chat channel: every connection subscribes to :chat,
|
|
17
|
-
# and whatever one connection sends is broadcast to everyone on it
|
|
18
|
-
# (including itself), prefixed with the authenticated subject when there
|
|
19
|
-
# is one.
|
|
20
|
-
#
|
|
21
|
-
# Defined inside a module, not at this script's own top level -- self at a
|
|
22
|
-
# script's top level is the main object, which is *not* Ractor-shareable,
|
|
23
|
-
# so a proc built there fails Server#run's Ractor.make_shareable check.
|
|
24
|
-
# Module bodies are always shareable, same as StateRactor#update's block
|
|
25
|
-
# requirement.
|
|
26
|
-
module ChatServer
|
|
27
|
-
# REDIS_URL set (by an app scaffolded with --redis, or by hand) wraps the
|
|
28
|
-
# registry so :chat also fans out to every other Monk::WebSocket::Server
|
|
29
|
-
# process sharing that Redis -- unset, it's in-process only. Either way
|
|
30
|
-
# the app code above never has to know which: RedisFanout has the exact
|
|
31
|
-
# same #register/#unregister/#count/#broadcast interface as Registry.
|
|
32
|
-
REGISTRY =
|
|
33
|
-
if (redis_url = ENV["REDIS_URL"])
|
|
34
|
-
require "monk/websocket/redis_fanout"
|
|
35
|
-
Monk::WebSocket::RedisFanout.new(Monk::WebSocket::Registry.new, redis_url: redis_url)
|
|
36
|
-
else
|
|
37
|
-
Monk::WebSocket::Registry.new
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
HANDLER = proc do |connection|
|
|
41
|
-
connection.subscribe(REGISTRY, :chat)
|
|
42
|
-
loop do
|
|
43
|
-
message = connection.read
|
|
44
|
-
break unless message
|
|
45
|
-
|
|
46
|
-
REGISTRY.broadcast(:chat, "#{connection.subject || "guest"}: #{message}")
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# This process holds the sockets, so it's the one that listens for other
|
|
52
|
-
# processes' broadcasts: with REDIS_URL, a subscriber connection, opened
|
|
53
|
-
# here at boot (an unreachable Redis fails right here). A plain Registry
|
|
54
|
-
# has nothing to listen to, and listen! does nothing.
|
|
55
|
-
ChatServer::REGISTRY.listen!
|
|
56
|
-
|
|
57
|
-
authenticate = defined?(Monk::Auth) && !!Monk::Auth.config
|
|
58
|
-
port = ENV.fetch("WS_PORT", "9293").to_i
|
|
59
|
-
# Defaults to public_url (config/settings.rb) so one PUBLIC_URL env var
|
|
60
|
-
# keeps this in sync with the app's actual origin instead of two vars
|
|
61
|
-
# drifting apart; set WS_ALLOWED_ORIGINS directly for anything more, e.g.
|
|
62
|
-
# more than one origin (comma-separated).
|
|
63
|
-
allowed_origins = ENV.fetch("WS_ALLOWED_ORIGINS", Monk::Settings[:public_url]).split(",")
|
|
64
|
-
|
|
65
|
-
server = Monk::WebSocket::Server.new(port: port, authenticate: authenticate, allowed_origins: allowed_origins)
|
|
66
|
-
puts "Monk::WebSocket::Server listening on ws://0.0.0.0:#{port} " \
|
|
67
|
-
"(authenticate: #{authenticate}, redis fan-out: #{ENV["REDIS_URL"] ? "on" : "off"})"
|
|
68
|
-
server.run(&ChatServer::HANDLER)
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Sends a magic link from bin/jobs instead of the login request. The token
|
|
2
|
-
# is created here, right before it's sent, so the raw token is never
|
|
3
|
-
# stored anywhere -- not even in the job queue, which a plain
|
|
4
|
-
# Monk::Mail.deliver_later of the link would do (Monk's
|
|
5
|
-
# docs/adr/0014-mail-from-jobs-and-login-links-created-in-the-job.md).
|
|
6
|
-
# Enqueue it from your login route, after your own per-email rate limit
|
|
7
|
-
# and with a redirect_to already checked against redirect_allowlist:
|
|
8
|
-
#
|
|
9
|
-
# post("/auth/request") do
|
|
10
|
-
# SendLoginLink.enqueue(params[:email])
|
|
11
|
-
# json(sent: true)
|
|
12
|
-
# end
|
|
13
|
-
class SendLoginLink < Monk::Job
|
|
14
|
-
queue "mailers"
|
|
15
|
-
# About 50 seconds of retries: a login email minutes late, after the
|
|
16
|
-
# user has likely asked for another, is worse than none.
|
|
17
|
-
max_attempts 3
|
|
18
|
-
never_retry Monk::InvalidRedirectError
|
|
19
|
-
|
|
20
|
-
def self.perform(email, redirect_to = nil)
|
|
21
|
-
token = Monk::Auth.request_login(email, redirect_to: redirect_to)
|
|
22
|
-
# Your callback route; config/settings.rb's public_url is the origin.
|
|
23
|
-
link = "#{Monk::Settings[:public_url]}/auth/callback/#{token}"
|
|
24
|
-
# Calls config/auth.rb's deliver: (AppMailer::MAGIC_LINK) -- a
|
|
25
|
-
# synchronous send, here in the job.
|
|
26
|
-
Monk::Auth.deliver_link(email: email, link: link, token: token)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
class App < Monk::Base
|
|
2
|
-
views "app/views"
|
|
3
|
-
layout "layouts/app"
|
|
4
|
-
assets "public"
|
|
5
|
-
|
|
6
|
-
# State shared across requests lives in a StateRactor; the update block is
|
|
7
|
-
# built here, where self is shareable, not inline in the route.
|
|
8
|
-
hits = Monk::StateRactor.new(0)
|
|
9
|
-
increment = Ractor.make_shareable(proc { |n| n + 1 })
|
|
10
|
-
|
|
11
|
-
get("/") { @title = "App"; render "index", hits: hits.value }
|
|
12
|
-
|
|
13
|
-
# Change state, then tell every open page that shows it. Monk::Live.patch
|
|
14
|
-
# renders the partial once and pushes it to the "hits" topic's subscribers.
|
|
15
|
-
post("/hit") do
|
|
16
|
-
Monk::Live.patch("hits", to: "#hits", partial: "live/_hits", hits: hits.update(&increment))
|
|
17
|
-
redirect "/"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
get("/hello") { "hello from monk" }
|
|
21
|
-
get("/api/hello") { json(message: "hello from monk") }
|
|
22
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<h1>Monk::Live</h1>
|
|
2
|
-
<p>
|
|
3
|
-
Open this page in two tabs and press the button in one: the counter in the
|
|
4
|
-
other updates by itself. The server pushes the new HTML over a WebSocket;
|
|
5
|
-
there is no polling and no page JavaScript of your own.
|
|
6
|
-
</p>
|
|
7
|
-
|
|
8
|
-
<%# live_topic makes this element's page subscribe to the "hits" topic. %>
|
|
9
|
-
<p <%= live_topic "hits" %>>Hits so far: <%= render "live/_hits", hits: locals[:hits], layout: false %></p>
|
|
10
|
-
|
|
11
|
-
<form method="post" action="/hit"><button>+1</button></form>
|
|
12
|
-
|
|
13
|
-
<p>
|
|
14
|
-
The pieces: <code>live_topic</code> in this view, the partial
|
|
15
|
-
<code>app/views/live/_hits.erb</code>, <code>Monk::Live.patch</code> in
|
|
16
|
-
<code>POST /hit</code> (<code>app/app.rb</code>), and the rules and Redis
|
|
17
|
-
wiring in <code>config/live.rb</code>.
|
|
18
|
-
</p>
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
require "bundler/setup"
|
|
3
|
-
require_relative "../config/settings"
|
|
4
|
-
|
|
5
|
-
# config/auth.rb only exists if this app was scaffolded with --auth -- a
|
|
6
|
-
# missing file is a harmless no-op, the same way config/settings.rb treats
|
|
7
|
-
# a missing dotenv gem. Present or not, it's what decides whether this
|
|
8
|
-
# process authenticates connections below.
|
|
9
|
-
begin
|
|
10
|
-
require_relative "../config/auth"
|
|
11
|
-
rescue LoadError
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Monk::Live: the browsers' sockets end here. The handler takes their
|
|
15
|
-
# subscribe/unsubscribe messages, checks each topic against the rules in
|
|
16
|
-
# config/live.rb, and relays whatever bin/server's process publishes over
|
|
17
|
-
# Redis.
|
|
18
|
-
require_relative "../config/live"
|
|
19
|
-
|
|
20
|
-
# This process holds the browsers' sockets, so it's the only one that
|
|
21
|
-
# listens for updates published elsewhere (bin/server, bin/jobs): the
|
|
22
|
-
# fanout's subscriber connection is opened here, at boot, and an
|
|
23
|
-
# unreachable Redis/Postgres fails right here.
|
|
24
|
-
Monk::Live.listen!
|
|
25
|
-
|
|
26
|
-
# With Monk::Auth (--auth), a socket with a valid session gets its user,
|
|
27
|
-
# and one without -- a visitor, or a session since revoked -- comes in
|
|
28
|
-
# anonymous instead of refused. The rules in config/live.rb decide what
|
|
29
|
-
# each may subscribe to: a topic is open to visitors only if its rule says
|
|
30
|
-
# `anonymous: true`, like the demo's "hits". Without Monk::Auth every
|
|
31
|
-
# socket is anonymous.
|
|
32
|
-
authenticate = defined?(Monk::Auth) && Monk::Auth.config ? :optional : false
|
|
33
|
-
port = ENV.fetch("WS_PORT", "9293").to_i
|
|
34
|
-
# Defaults to public_url (config/settings.rb) so one PUBLIC_URL env var
|
|
35
|
-
# keeps this in sync with the app's actual origin instead of two vars
|
|
36
|
-
# drifting apart; set WS_ALLOWED_ORIGINS directly for anything more, e.g.
|
|
37
|
-
# more than one origin (comma-separated).
|
|
38
|
-
allowed_origins = ENV.fetch("WS_ALLOWED_ORIGINS", Monk::Settings[:public_url]).split(",")
|
|
39
|
-
|
|
40
|
-
server = Monk::WebSocket::Server.new(port: port, authenticate: authenticate, allowed_origins: allowed_origins)
|
|
41
|
-
puts "Monk::Live WebSocket server listening on ws://0.0.0.0:#{port} (authenticate: #{authenticate})"
|
|
42
|
-
server.run(&Monk::Live::HANDLER)
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Monk::Live wiring, required by both processes: config/load.rb (this app
|
|
2
|
-
# publishes updates, e.g. from a route) and bin/websocket_server (the browsers'
|
|
3
|
-
# sockets terminate there and are handed the updates).
|
|
4
|
-
#
|
|
5
|
-
# They are separate processes, so *something* has to carry a publish from
|
|
6
|
-
# one to the other. `monk new --live --postgres` (and not --redis) wired
|
|
7
|
-
# this file instead of the Redis-based default -- Postgres LISTEN/NOTIFY
|
|
8
|
-
# carries the publish instead, reusing the exact DB_* env vars
|
|
9
|
-
# config/persistence.rb already reads, so there's no Redis to run. The
|
|
10
|
-
# tradeoff: a single broadcast is capped at just under 8000 bytes
|
|
11
|
-
# (Monk::WebSocket::PgFanout::MAX_NOTIFY_PAYLOAD_BYTES, Postgres's own
|
|
12
|
-
# NOTIFY limit) -- regenerate with --redis instead if that becomes a real
|
|
13
|
-
# constraint. Full design in the monk gem's own docs/design/live-pg-fanout.md.
|
|
14
|
-
require_relative "settings"
|
|
15
|
-
require "monk/live"
|
|
16
|
-
require "monk/websocket/pg_fanout"
|
|
17
|
-
|
|
18
|
-
# Where the browser opens its WebSocket (read by the layout). In
|
|
19
|
-
# development there's no reverse proxy in front, so this is the direct WS
|
|
20
|
-
# port; outside development it defaults to a /ws path under public_url
|
|
21
|
-
# (config/settings.rb) -- matching the path-based proxy routing
|
|
22
|
-
# docs/guides/deploying.md's "Adding Monk::WebSocket" section sets up, so
|
|
23
|
-
# setting PUBLIC_URL alone keeps this in sync instead of two env vars
|
|
24
|
-
# drifting apart. Override with LIVE_WS_URL directly if your setup doesn't
|
|
25
|
-
# fit that shape.
|
|
26
|
-
default_live_ws_url =
|
|
27
|
-
if Monk.env.development?
|
|
28
|
-
"ws://localhost:9293"
|
|
29
|
-
else
|
|
30
|
-
Monk::Settings[:public_url].sub(/\Ahttps:\/\//, "wss://").sub(/\Ahttp:\/\//, "ws://") + "/ws"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
Monk::Settings.configure do
|
|
34
|
-
optional :live_ws_url, default: default_live_ws_url
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
Monk::Live.configure(
|
|
38
|
-
registry: Monk::WebSocket::PgFanout.new(
|
|
39
|
-
Monk::WebSocket::Registry.new,
|
|
40
|
-
pg_opts: {
|
|
41
|
-
host: ENV.fetch("DB_HOST", "127.0.0.1"),
|
|
42
|
-
port: ENV.fetch("DB_PORT", "5432").to_i,
|
|
43
|
-
user: ENV.fetch("DB_USER", "postgres"),
|
|
44
|
-
password: ENV.fetch("DB_PASSWORD", "postgres"),
|
|
45
|
-
dbname: ENV.fetch("DB_NAME", "app_development"),
|
|
46
|
-
},
|
|
47
|
-
),
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
# Who may subscribe to what. Nothing is allowed unless a rule says so, and an
|
|
51
|
-
# anonymous connection is denied unless the rule opts in with `anonymous: true`.
|
|
52
|
-
# The rule blocks live in a module because they have to be Ractor-shareable
|
|
53
|
-
# (self at the top of this file is not).
|
|
54
|
-
module AppLive
|
|
55
|
-
# The demo counter is public. A real rule looks at who is asking:
|
|
56
|
-
# proc { |subject, topic| topic == "contacts:#{subject}" }
|
|
57
|
-
PUBLIC = proc { |_subject, _topic| true }
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
Monk::Live.authorize("hits", anonymous: true, &AppLive::PUBLIC)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
gem "net-smtp" # Monk::Mail's smtp:// transport (config/mail.rb)
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Same shape as the base Dockerfile, plus libpq: the pg gem's native
|
|
2
|
-
# extension needs libpq-dev (headers) to compile in the builder stage and
|
|
3
|
-
# libpq5 (the runtime lib alone, no headers) in the final image.
|
|
4
|
-
FROM ruby:4.0-slim AS builder
|
|
5
|
-
WORKDIR /app
|
|
6
|
-
|
|
7
|
-
RUN apt-get update -qq \
|
|
8
|
-
&& apt-get install -y --no-install-recommends build-essential libpq-dev \
|
|
9
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
10
|
-
|
|
11
|
-
COPY Gemfile Gemfile.lock* ./
|
|
12
|
-
RUN bundle install
|
|
13
|
-
|
|
14
|
-
FROM ruby:4.0-slim
|
|
15
|
-
WORKDIR /app
|
|
16
|
-
|
|
17
|
-
RUN apt-get update -qq \
|
|
18
|
-
&& apt-get install -y --no-install-recommends libpq5 \
|
|
19
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
20
|
-
|
|
21
|
-
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
|
22
|
-
COPY . .
|
|
23
|
-
|
|
24
|
-
# Matches bin/server's own default (PORT overrides both, e.g. on a
|
|
25
|
-
# platform that assigns its own). bin/websocket_server (WS_PORT default
|
|
26
|
-
# 9293) is a separate process/deploy unit -- run this same image with
|
|
27
|
-
# `bin/websocket_server` as the command instead of publishing another
|
|
28
|
-
# port from this Dockerfile -- see docs/guides/deploying.md. With --jobs,
|
|
29
|
-
# bin/jobs is another one, the same way: this image, `bin/jobs` as the
|
|
30
|
-
# command, no port at all.
|
|
31
|
-
EXPOSE 9292
|
|
32
|
-
CMD ["bin/server", "--bind", "0.0.0.0"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
gem "redis"
|
|
File without changes
|