Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rails + PostgreSQL + Docker – začetna predloga
Predloga za razvojno okolje Ruby on Rails v Dockerju. Vsebuje samo infrastrukturo (Docker, Compose, okoljske spremenljivke, ignore datoteke). Rails aplikacijo ustvariš znotraj kontejnerja z rails new, zato na računalniku ne potrebuješ nameščenega Rubyja.
Sklad
| Komponenta | Različica | Opomba |
|---|---|---|
| Ruby | 4.0.9 | uradna slika ruby:4.0.9-slim (minimalen Debian) |
| Ruby on Rails | zadnja stabilna | namesti se z gem install rails |
| PostgreSQL | 18 (PG_MAJOR) |
uradna slika postgres:18; klient iz repozitorija PGDG |
| JavaScript | importmap | privzeto v Rails 8; Node.js ni potreben (glej Če potrebuješ Node.js) |
| Docker Compose | v2 | servisa app in db |
Datoteke
| Datoteka | Namen |
|---|---|
Dockerfile |
slika za razvoj: Ruby, sistemske knjižnice (build-essential, git, libpq-dev, libyaml-dev, pkg-config, postgresql-client-18), repozitorij PGDG, uporabnik app (UID 1000) |
docker-compose.yml |
servis app (Rails na vratih 3000) in servis db (PostgreSQL) ter volumna bundle in pgdata |
.env.example |
predloga okoljskih spremenljivk (različica PostgreSQL in dostop do baze); kopiraš jo v .env |
.gitea/template |
seznam datotek, v katerih Gitea ob ustvarjanju repozitorija iz predloge zamenja spremenljivke z imenom repozitorija |
.dockerignore |
v sliko ne kopira skrivnosti, .git, dnevnikov in začasnih datotek |
.gitignore |
v Git ne shrani .env, ključev za credentials, dnevnikov ipd. |
Zasnova
- Osnova je
ruby:4.0.9-slim, enako kot v Dockerfile, ki ga ustvari Rails. Je precej manjša od polne slike, glibc pa omogoča uporabo vnaprej prevedenih gemov (nokogiri, pg ...). Razvojna orodja, ki jihslimnima, so dodana zapt-get:build-essentialinpkg-configza prevajanje nativnih gemov,libpq-devza gempg,libyaml-devza gempsych,gitza geme, nameščene iz Git repozitorijev,postgresql-client-<PG_MAJOR>zarails dbconsoleindb:schema:dumpv formatu SQL.
- Klient PostgreSQL je iz uradnega repozitorija PGDG (apt.postgresql.org), ne iz Debiana. Debian ima navadno starejšo glavno različico,
pg_dumppa zavrne izvoz iz novejšega strežnika. Različico za strežnik (postgres:<PG_MAJOR>) in klient določa ena spremenljivkaPG_MAJORv.env(privzeto 18). Compose jo preda Dockerfile kot build argument. Po spremembiPG_MAJORzgradi sliko znova (docker compose build). Pri prehodu na novo glavno različico strežnika obstoječi podatki v volumnupgdataniso združljivi, zato jih je treba izvoziti in uvoziti (ali volume izbrisati). - Geme hrani volume
bundle, ki je priklopljen na/usr/local/bundle. To jeGEM_HOMEuradne Ruby slike in je že vPATH.gem installinbundle installzato pišeta v isto mapo, gemi pa se ohranijo med zagoni kontejnerja. BUNDLE_PATHnamenoma ni nastavljen. Z njim bibundle installgeme nameščal v drugo mapo kotgem install, izvršljive datoteke (rails,rake) pa ne bi bile vPATH.- Kontejner teče kot uporabnik
app(UID 1000), zato so datoteke, ki jih ustvari (npr.rails new, migracije), na računalniku v lasti tvojega uporabnika. Če ima tvoj uporabnik drug UID (preveri zid -u), ga spremeni vDockerfilein vdocker-compose.yml(user:). - Koda je priklopljena z
.:/app, zato se spremembe takoj vidijo v kontejnerju, brez ponovne gradnje slike. - Podatke baze hrani volume
pgdata, zato ostanejo tudi podocker compose down. Priklopljen je na/var/lib/postgresql(ne na/var/lib/postgresql/data), kot zahteva slikapostgresod različice 18 naprej. Podatki so v podmapi<PG_MAJOR>/docker, kar omogoča nadgradnjo spg_upgrade --link. - Servis
dbima healthcheck (pg_isready), servisapppa se zažene šele, ko je baza pripravljena na povezave. - Ob zagonu servisa
appse najprej izvedebin/rails db:prepare, ki ustvari bazo (če še ne obstaja) in izvede čakajoče migracije. Podocker compose down -vzato baze ni treba ustvarjati ročno.
Nov projekt iz predloge
1. Ustvari repozitorij iz predloge
Repozitorij rails-docker-starter je v Gitei označen kot predloga (Make repository a template).
- V Gitei izberi + → New Repository.
- V polju Template izberi
rails-docker-starter. - Obkljukaj Git Content. Ostale možnosti (webhooki, oznake ...) niso potrebne.
- Vpiši ime novega repozitorija (npr.
moj-projekt) in klikni Create Repository.
Nov repozitorij dobi datoteke predloge brez njene zgodovine. Gitea v datotekah, naštetih v .gitea/template, zamenja spremenljivke z imenom repozitorija: v .env.example tako ${REPO_NAME_SNAKE}_development postane moj_projekt_development.
Nato repozitorij kloniraj:
git clone <url-novega-repozitorija>
cd moj-projekt
Če predlogo namesto tega kloniraš neposredno (git clone, nato rm -rf .git && git init), Gitea spremenljivk ne zamenja. V .env moraš ${REPO_NAME_SNAKE} zamenjati ročno, sicer Compose spremenljivko razume kot prazno in baza se imenuje _development.
2. Nastavi okoljske spremenljivke
cp .env.example .env
V .env preveri ime baze in vpiši uporabnika in geslo. APP_DATABASE_HOST naj ostane db (ime servisa v Compose).
3. Zgradi sliko in namesti Rails
docker compose build
docker compose run --rm app gem install rails
4. Ustvari Rails aplikacijo
docker compose run --rm app rails new . --database=postgresql --skip-docker
--skip-dockerprepreči, da bi Rails ustvaril svoj (produkcijski)Dockerfilein prepisal obstoječega.- Ko vpraša, ali naj prepiše
.gitignore, odgovorin. Predloga že vsebuje vse vrstice, ki jih doda Rails. - Ko vpraša, ali naj prepiše
README.md, odgovorin, sicer izgubiš ta navodila. Navodila za aplikacijo lahko pozneje dopišeš sem.
5. Poveži Rails z bazo
V config/database.yml dodaj nastavitve povezave v razdelek default, da veljajo za development in test:
default: &default
adapter: postgresql
encoding: unicode
max_connections: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
# Povezava na bazo v kontejnerju db (vrednosti iz .env)
host: <%= ENV["APP_DATABASE_HOST"] %>
port: <%= ENV.fetch("APP_DATABASE_PORT") { 5432 } %>
username: <%= ENV["APP_DATABASE_USERNAME"] %>
password: <%= ENV["APP_DATABASE_PASSWORD"] %>
development:
<<: *default
database: <%= ENV["APP_DATABASE"] %>
test:
<<: *default
database: <%= ENV["APP_DATABASE"] %>_test
Brez teh nastavitev se Rails poskuša povezati prek lokalnega socketa in javi PG::ConnectionBad: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed.
6. Dovoli web-console iz omrežja Docker
Brskalnik dostopa do aplikacije prek omrežja Docker (npr. 172.27.0.1), web-console pa privzeto dovoli le 127.0.0.1. V dnevniku se zato izpiše Cannot render console from 172.27.0.1!, konzola na strani z napako pa se ne prikaže. V config/environments/development.rb dodaj:
# Dovoli web-console za zahteve iz omrežij Docker (privzeti bazeni naslovov).
config.web_console.allowed_ips = %w[172.16.0.0/12 192.168.0.0/16]
7. Zaženi aplikacijo
docker compose up
Ob zagonu se samodejno izvede bin/rails db:prepare, ki ustvari bazo. Aplikacija je dosegljiva na http://localhost:3000.
8. Odkomentiraj namestitev gemov v Dockerfile
Ko obstajata Gemfile in Gemfile.lock, v Dockerfile odkomentiraj:
COPY --chown=app:app Gemfile Gemfile.lock ./
RUN bundle install
Ob gradnji slike se tako namestijo gemi, Docker pa to plast shrani v predpomnilnik.
Pogosti ukazi
| Opravilo | Ukaz |
|---|---|
| Zagon | docker compose up |
| Zagon v ozadju | docker compose up -d |
| Ustavitev | docker compose down |
| Rails konzola | docker compose run --rm app bin/rails console |
| Migracije | docker compose run --rm app bin/rails db:migrate |
| Generator | docker compose run --rm app bin/rails generate model Company name:string |
| Testi | docker compose run --rm app bin/rails test |
| Lupina v kontejnerju | docker compose run --rm app bash |
| Konzola PostgreSQL | docker compose exec db psql -U <uporabnik> <baza> |
| Dnevnik | docker compose logs -f app |
Če aplikacija že teče (docker compose up), lahko namesto run --rm uporabiš exec, ki ukaz izvede v obstoječem kontejnerju.
Dodajanje gemov
docker compose run --rm app bundle add <ime_gema>
Po ročni spremembi Gemfile:
docker compose run --rm app bundle install
Volume bundle prekrije geme, nameščene ob gradnji slike. Po spremembi Gemfile zato vedno poženi bundle install v kontejnerju; samo ponovna gradnja slike ni dovolj.
Če potrebuješ Node.js
Privzeti Rails 8 projekt Node.js ne potrebuje: JavaScript se naloži prek importmap, sredstva obdela Propshaft. Tudi Tailwind (--css=tailwind) in Dart Sass (dartsass-rails) uporabljata samostojni izvršljivi datoteki brez npm.
Node.js je potreben, če pri rails new izbereš:
--javascript=esbuild,rollupaliwebpack(jsbundling-rails),--css=bootstrap,bulma,postcssalisass(cssbundling-rails),
ali če uporabljaš knjižnice, ki jih je treba prevesti (npr. React z JSX).
Paket nodejs iz Debiana za to ne zadošča, ker ne vsebuje npm in je pogosto zastarel. Node.js raje prekopiraj iz uradne slike (pred vrstico USER app):
COPY --from=node:24-slim /usr/local/bin/node /usr/local/bin/
COPY --from=node:24-slim /usr/local/lib/node_modules /usr/local/lib/node_modules
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
Različico (24) izberi glede na aktualni LTS. Če potrebuješ yarn, dodaj še RUN npm install -g yarn (prav tako pred USER app).
Odpravljanje težav
Permission denied pri gem install ali bundle install
Volume bundle je verjetno nastal s starejšo različico slike, ko je bila mapa v lasti uporabnika root. Odstrani ga in zgradi sliko znova:
docker compose down
docker volume ls # poišči <projekt>_bundle
docker volume rm <projekt>_bundle
docker compose build
could not translate host name "db" ali connection refused
Preveri, da je v .env nastavljeno APP_DATABASE_HOST=db in da teče servis baze (docker compose ps, stanje healthy). Pri docker compose run Compose sicer počaka na healthcheck, pri ročnem zagonu servisa db pa PostgreSQL ob prvem zagonu potrebuje nekaj sekund za inicializacijo.
PG::ConnectionBad: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed
Rails ne uporablja nastavitev iz .env in se poskuša povezati lokalno. Preveri config/database.yml (glej korak 5) in znova zaženi servis app (docker compose restart app).
Kontejner db se ustavi z Error: in 18+, these Docker images are configured to store database data in a format which is compatible with "pg_ctlcluster"
Volume pgdata je priklopljen na /var/lib/postgresql/data, slika postgres od različice 18 naprej pa pričakuje /var/lib/postgresql. Popravi priklop v docker-compose.yml. Če so v volumnu podatki starejše glavne različice, jih nadgradi s pg_upgrade ali izvozi in uvozi, sicer volume izbriši (docker volume rm <projekt>_pgdata).
A server is already running
Ostala je datoteka s PID-om strežnika:
rm tmp/pids/server.pid
Ponastavitev baze od začetka
docker compose down -v # izbriše VSE volumne, tudi podatke v bazi
Opombe
- Predloga je namenjena razvoju. Za produkcijo uporabi Dockerfile, ki ga ustvari
rails new(brez--skip-docker), ali Kamal. .envnikoli ne shranjuj v Git. V repozitorij gre samo.env.example.