-
-
Save rubys/ae5f24a4dc72936a67c6c44ee3c2a0d6 to your computer and use it in GitHub Desktop.
The following will create a "high availability" visitor counter app with postgresql and redis; as well as a stage app that runs everything in one machine under docker compose.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
APPNAME=demo-$USER-$RANDOM | |
mkdir $APPNAME | |
cd $APPNAME | |
rails new . --database postgresql | |
bin/rails generate model Visitor counter:integer | |
bin/rails generate controller Visitors counter | |
bin/rails generate channel counter | |
cat << 'EOF' > app/controllers/visitors_controller.rb | |
class VisitorsController < ApplicationController | |
def counter | |
@visitor = Visitor.find_or_create_by(id: 1) | |
@visitor.update! counter: @visitor.counter.to_i + 1 | |
@visitor.broadcast_replace_later_to 'counter', | |
partial: 'visitors/counter' | |
end | |
end | |
EOF | |
cat << 'EOF' > app/views/visitors/counter.html.erb | |
<%= turbo_stream_from 'counter' %> | |
<div style="position: absolute; top: 0; left: 0; height: 100vh; width: 100vw"> | |
<svg width="100vw" height="100vh" viewBox="0 0 112 112" width="112" xmlns="http://www.w3.org/2000/svg"> | |
<circle cx="56" cy="56" r="56" fill="#D30001"/> | |
<path d="m100.082357 48.9995403v4.1135034h-7.3003388v1.89854h3.6840717c1.9725091 0 4.0725341 1.4664311 4.1979971 3.9665124l.005913.2373977v1.5821167c-.087824 3.007959-2.5431211 4.1390018-4.0715389 | |
4.2011773l-.1323712.0027328h-7.3907451v-4.0909018l7.4811518-.0226016v-1.9889467h-3.4806567c-1.7752583 0-4.0818321-1.3389153-4.2199942-3.9549201l-.0065176-.24899v-1.423905c0-2.6982402 2.2782129-4.182853 4.065464-4.2678491l.1610478-.003866zm-18.691579 | |
0v11.8658752h6.1702551v4.1361051h-10.7357919v-16.0019803zm-6.4414751 0v16.0019803h-4.5881385v-16.0019803zm-15.210922 0h4.4073251l.187724.0066812c.0338609.0022735.0689457.0051499.1051601.0086643l.2300875.0290178c1.2913829.1985476 3.5463816 1.1213816 | |
3.6751708 3.9068587l.0057677.2526881v11.7980702h-4.2717151v-2.8252084h-4.1361051v2.8252084h-4.4073251v-11.7980702c0-1.3184306 1.0040826-4.0468495 3.946899-4.197411zm-19.7398519-.0027581 | |
8.5801857.0005749.2389234.0367462.1479459.029417.2741161.0653582.2125198.0599068.2323225.0747182c.0401793.0137704.0810402.0282201.122511.0433804l.2555691.0997376.2667618.1182852c1.3560515.6402866 3.0026855 2.0321583 3.0026855 5.016294 0 3.1830781-1.5465241 | |
4.5014899-2.6988362 5.0420477l-.2109651.0925045-.1988828.0758655-.1839577.0608186-.1661898.0473636-.2097508.0493001-.2596493.0418363 5.0056895 | |
5.0505836h-6.3749589l-3.7262083-3.8608906v3.8608906h-4.3098314zm22.0070603-3.0869193.4449917.4226807-.242968.1779881-.3482331.2693365-.1998573.1629204c-5.2398967-3.8745715-9.6476454-5.4221409-13.197119-5.8153537l-.5259807-.0504708c-1.0390742-.0842126-2.0007861-.0698101-2.8844302.0115462l-.4353132.0461111c-.0714668.0085662-.1423907.0175608-.2127712.0269653l-.4157595.0612005-.4026991.0701607-.3896194.0782415-.3765198.0854427c-.0616606.0147917-.1227746.0298468-.1833415.045147l-.3568339.0945957-.3436854.0995982-.3305174.1037213-.3173297.1069649-.3041225.109329-.2908956.1108137-.4115002.1670803-.5021902.2197615-.6533736.3088956-.610105.3005675c-4.6988866 | |
2.6219788-6.8539294 6.8460711-7.7682002 | |
10.8866463l-.1223101.5757838c-.0380504.1913833-.0734278.3821576-.1062732.5721301l-.0910804.5673196-.0767318.5613521-.0632275.5542277c-.0094594.0917134-.0183914.1830817-.0268134.2740808l-.044554.5413722-.0331601.5313556c-.0046242.0876603-.0088087.1748551-.0125713.2615602l-.0176525.5141618-.0083693.5012531.0000696.4871876.0140806.7018779.0283195.6637229.0397089.6216637.0482492.5756999.0539402.5258317.0758481.6167879.0741462.511937.0800002.4783756.0685995.3540863h-17.855317l.05849-.4417253.0463368-.2951448.0630206-.3647242.1132819-.5892069.1093787-.5150907.1820265-.7785088.1661376-.6486772.1259233-.4615943.2130474-.7338225.1589655-.5155042.1731728-.5354699.1879463-.5545226.2032857-.572662.2191913-.5898883.2356628-.6062014.2527004-.6216012c.043568-.1048328.0878694-.2102691.1329162-.3162901l.279318-.6429887.2977707-.6561056.3167894-.6683092.336374-.6795997.3565249-.689977c.3667889-.6948611.7646529-1.4039184 | |
1.1961393-2.1230624 4.7463501-7.9105834 12.8377469-13.9000252 19.414832-14.4876686 5.0453806-.5054094 9.8925436.9276823 13.9443628 | |
2.8796435l.6499858.3208582.6354768.3286093.6204019.335015c.1021126.0562949.2035736.1128007.304371.1694892l.5967286.3421013.580239.3451439.5631836.3468411.5455624.3471932.5273753.3461999.5086223.3438614c.0831762.0570406.1655475.1139277.247102.1706333l.479432.3378312.4592644.3321294.438531.3250825.4172317.3166902.5846736.4563569.5335674.4299071.6286237.5242179.6463432.5614015zm-30.7001056 | |
14.5713243 2.4409801.881465c.1130083.8852319.2731034 1.7233771.4410464 | |
2.4882761l.1013936.4499406-2.7122001-.9718717-.0338347-.2121618-.0660421-.4755843-.0611601-.5412195c-.0480285-.4774602-.0875814-1.0199003-.1101831-1.6188444zm31.5067239-7.6619652h-1.5143117c-.9400238 | |
0-1.2391224.409772-1.3342901.670536l-.0282266.0950339c-.003237.014073-.0058266.0271526-.0078982.0390732l-.0081573.0715239-.0001295 | |
3.9153864h4.1361051l-.0018533-3.9347694-.0102612-.0669913-.0257207-.0987241c-.0835357-.2591507-.3509135-.6910686-1.2052565-.6910686zm-50.4921242.339025 2.5991917.94927-.408641.9515839c-.2124882.4994644-.4277796 1.0148142-.6033575 | |
1.457745l-.1180849.3028712-2.5991917-.94927.1323662-.3453033.2583889-.6392034.3057111-.7281974.3254875-.7536244c.0362438-.0827943.0723437-.1648823.1081297-.2458716zm35.4451209-.1434449h-3.4568439v3.6588673h3.4343968l.0547106-.025392.0865984-.0488983.1147536-.0786822c.2926428-.2211448.7316071-.7149797.7316071-1.6876847s-.4289878-1.4565634-.7149797-1.6710573l-.1121455-.0760741-.0846303-.0469301zm-15.4426456-.7606218 | |
1.6273201 1.2882951c-.1808134.705172-.3182315 1.410344-.4122545 2.115516l-.0623806.528879-1.830735-1.4465067c.1808134-.81366.3842284-1.6499217.67805-2.4861834zm4.0004951-6.3058651 1.017075 1.5369134c-.3977893.4158707-.7666485.8317413-1.0950055 | |
1.2707561l-.2384928.3339623-1.0848801-1.6273201c.40683-.5198383.8814651-1.0396767 1.4013034-1.5143117zm-16.1827936-3.3450467 1.6047183 1.4013034c-.40683.4237812-.8009465.8729894-1.1728146 1.3285542l-.3640987.4569775-1.7403284-1.4917101c.5198383-.5650416 | |
1.08488-1.1300833 1.6725234-1.695125zm22.3982521-.0904067.4972366 1.4917101c-.5243586.162732-1.0487173.3688592-1.573076.6068095l-.393269.1842488-.5198384-1.559515c.5650417-.2486184 1.2204901-.4972367 1.9889468-.7232534zm5.28879-.54244c.5786027.0361627 | |
1.1716705.1012555 1.7792033.2068505l.4583618.0869712-.0904067 1.4013034c-.596684-.1265694-1.193368-.2097435-1.790052-.2495224l-.447513-.0216976zm-18.5559686-6.2380601 1.017075 | |
1.559515c-.4407325.2203663-.8687516.4661594-1.3031274.7278443l-.437201.2666291-1.0396767-1.5821167c.610245-.3616267 1.1978884-.67805 | |
1.7629301-.9718717zm18.5107653.6328467.0904067-1.49171.4435073.1305564.3839803.1203252.3285458.1099079.2772037.0993048.3284915.128669.296488.1327112.1341451.0695838-.0904067 | |
1.5143117c-.4821689-.1958811-.9643378-.381717-1.4532035-.5575078zm-8.5434301-2.8252084.4520333 1.3787017h-.2260167c-.4915862 0-.9831725.0127134-1.4747588.0476754l-.4915862.0427313-.4294317-1.3334984c.745855-.0904067 1.4691084-.13561 2.1697601-.13561z" | |
fill="#fff"/> | |
</svg> | |
</div> | |
<div style="position: absolute; font-size: 25vh; font-weight: bold; font-family: Calibre sans-serif; color: white; top: 65vh; left: 0; width: 100%; text-align: center"> | |
<%= render "counter", visitor: @visitor %> | |
</div> | |
EOF | |
cat << 'EOF' > app/views/visitors/_counter.html.erb | |
<%= turbo_frame_tag(dom_id visitor) do %> | |
<%= visitor.counter.to_i %> | |
<% end %> | |
EOF | |
cat << 'EOF' > config/routes.rb | |
Rails.application.routes.draw { root "visitors#counter" } | |
EOF | |
fly launch --yes --name $APPNAME | |
bin/rails generate dockerfile --force --compose | |
fly apps create $APPNAME-stage --org personal | |
flyctl ips allocate-v4 --shared --app $APPNAME-stage | |
flyctl ips allocate-v6 --app $APPNAME-stage | |
fly secrets set RAILS_MASTER_KEY=$(cat config/master.key) --app $APPNAME-stage | |
cat fly.toml | sed "s/^app =.*/app = \"$APPNAME-stage\"/" | \ | |
sed "s/^console_command =.*/console_command = \"\/usr\/bin\/bash\"/" | \ | |
sed "s/^\[build\].*/&\n \ \ dockerfile = \"Dockerfile.stage\"/" | \ | |
sed "/^ *release_command/d" | \ | |
sed "s/^ *memory = '1gb'/ memory = '2gb'/" > fly-stage.toml | |
cat << 'EOD' > Dockerfile.stage | |
# syntax = docker/dockerfile:1 | |
# "Docker in Docker" | |
FROM cruizba/ubuntu-dind | |
# boot script | |
COPY <<-"EOF" /usr/local/bin/boot.sh | |
nginx | |
sysctl.sh | |
start-docker.sh | |
sleep 1 | |
docker compose create postgres-db web | |
docker compose start web | |
docker compose exec web bin/rails db:prepare | |
docker compose up | |
EOF | |
RUN chmod +x /usr/local/bin/boot.sh | |
# rchab: Remote controlled Hot Air Balloon | |
RUN mkdir /etc/docker && \ | |
wget https://raw.githubusercontent.com/superfly/rchab/main/etc/docker/daemon.json -O /etc/docker/daemon.json && \ | |
wget https://raw.githubusercontent.com/superfly/rchab/main/docker-entrypoint.d/sysctl -O /usr/local/bin/sysctl.sh && \ | |
chmod +x /usr/local/bin/sysctl.sh | |
# nginx | |
RUN apt-get install -y nginx | |
COPY <<-"EOF" /etc/nginx/sites-enabled/default | |
server { | |
root /rails/public; | |
listen 3000; | |
listen [::]:3000; | |
error_page 502 @maintenance; | |
location / { | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Port 443; | |
proxy_set_header X-Forwarded-Proto https; | |
proxy_set_header X-Forwarded-Ssl on; | |
proxy_set_header Host $http_host; | |
proxy_pass http://0.0.0.0:3001; | |
proxy_redirect off; | |
} | |
location /cable { | |
proxy_pass http://0.0.0.0:3001; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "Upgrade"; | |
} | |
location @maintenance { | |
try_files /502.html =404; | |
} | |
} | |
EOF | |
# App | |
WORKDIR /rails | |
COPY . . | |
# adjust port in docker-compose.yml | |
RUN sed -i "s/3000:3000/3001:3000/" docker-compose.yml | |
# enable action cable from any origin | |
COPY <<-"EOF" config/initializers/cable_origin.rb | |
Rails.application.config.action_cable.disable_request_forgery_protection = true | |
EOF | |
# loading page | |
RUN cat public/500.html | \ | |
sed 's/<p>.*/<p>Hang tight, the system should be up shortly.<\/p>/' | \ | |
sed 's/<h1>.*/<h1>Running docker compose up<\/h1>/' | \ | |
sed 's/<title>.*/<title>docker compose up<\/title>/' | \ | |
sed 's/public\/500.html/public\/502.html/' | \ | |
sed '/<meta/i \ \ <meta http-equiv="refresh" content="5">' \ | |
> public/502.html | |
CMD boot.sh | |
EOD | |
fly deploy --ha=false --config fly-stage.toml | |
fly apps open --config fly-stage.toml | |
fly apps open --config fly-stage.toml | |
fly logs --app $APPNAME-stage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment