From 3fe3d9bab96bd484751e30ed774a3b11c7cc1f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20Friedrich?= Date: Tue, 27 Oct 2026 11:20:47 +0100 Subject: [PATCH] =?UTF-8?q?Za=C4=8Detna=20predloga=20za=20Rails=20razvojno?= =?UTF-8?q?=20okolje=20v=20Dockerju?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile na osnovi ruby:4.0.9-slim z razvojnimi orodji in klientom PostgreSQL iz repozitorija PGDG - docker-compose.yml s servisoma app (Rails) in db (PostgreSQL) - .env.example, .dockerignore in .gitignore - README z opisom sklada in navodili za nov projekt Co-Authored-By: Claude Opus 5.5 --- .dockerignore | 22 +++++ .env.example | 10 +++ .gitignore | 29 +++++++ CLAUDE.md | 11 +++ Dockerfile | 44 ++++++++++ README.md | 194 +++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 37 +++++++++ 7 files changed, 347 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fb81754 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +# Git +.git +.gitignore + +# Okoljske spremenljivke in skrivnosti +.env +.env.* +!.env.example +config/master.key +config/credentials/*.key + +# Dnevniki, začasne datoteke in naložene datoteke +log/* +tmp/* +storage/* +public/assets +node_modules + +# Docker +Dockerfile +docker-compose.yml +.dockerignore diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5864a5a --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# Kopiraj v .env in vpiši svoje vrednosti: cp .env.example .env + +# Glavna različica PostgreSQL za strežnik in klient v kontejnerju app +PG_MAJOR=18 + +APP_DATABASE=poslovni_imenik_development +APP_DATABASE_HOST=db +APP_DATABASE_PORT=5432 +APP_DATABASE_USERNAME=postgres +APP_DATABASE_PASSWORD=spremeni_me diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ed996b --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Okoljske spremenljivke in skrivnosti +.env +.env.* +!.env.example +/config/master.key +/config/credentials/*.key + +# Dnevniki in začasne datoteke +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep +/tmp/pids/* +!/tmp/pids/.keep + +# Naložene datoteke (Active Storage) +/storage/* +!/storage/.keep + +# Prevedena sredstva +/public/assets +/app/assets/builds/* +!/app/assets/builds/.keep +/node_modules + +# Urejevalniki in sistem +.vscode/ +.idea/ +.DS_Store diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..09fdd4d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,11 @@ +# Poslovni imenik + +## Jezik + +- Komunikacija z uporabnikom poteka v **slovenskem jeziku**. +- Vsi komentarji v kodi, README datoteke in ostala dokumentacija so v **slovenskem jeziku**. +- Imena spremenljivk, funkcij, razredov in ostalih identifikatorjev v kodi so v **angleškem jeziku**. + +## Izrazoslovje + +- Za Docker container uporabljaj izraz **kontejner** (kontejnerja, kontejnerju ...), ne prevoda "vsebnik". diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6c616e3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +FROM ruby:4.0.9-slim + +# Geme namešča v GEM_HOME slike (/usr/local/bundle), kjer je tudi volume "bundle" +ENV BUNDLE_JOBS=4 \ + BUNDLE_RETRY=3 + +# Glavna različica PostgreSQL; mora se ujemati s strežnikom (nastavi jo docker-compose.yml) +ARG PG_MAJOR=18 + +# Uradni repozitorij PostgreSQL (PGDG), da je klient iste različice kot strežnik +RUN apt-get update -y && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + && install -d /usr/share/postgresql-common/pgdg \ + && curl -fsSL -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \ + https://www.postgresql.org/media/keys/ACCC4CF8.asc \ + && . /etc/os-release \ + && echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt ${VERSION_CODENAME}-pgdg main" \ + > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update -y && apt-get install -y --no-install-recommends \ + build-essential \ + git \ + libpq-dev \ + libyaml-dev \ + pkg-config \ + postgresql-client-${PG_MAJOR} \ + && rm -rf /var/lib/apt/lists/* + +# Uporabnik app mora imeti pravico pisanja v mapo z gemi +RUN useradd -u 1000 -m app \ + && chown -R app:app /usr/local/bundle + +WORKDIR /app +RUN chown app:app /app + +USER app + +# Odkomentiraj, ko bo obstajal Gemfile (po rails new) +#COPY --chown=app:app Gemfile Gemfile.lock ./ +#RUN bundle install + +COPY --chown=app:app . . + +EXPOSE 3000 diff --git a/README.md b/README.md new file mode 100644 index 0000000..82377d1 --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ +# 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](#če-potrebuješ-nodejs)) | +| 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` | +| `.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 jih `slim` nima, so dodana z `apt-get`: + - `build-essential` in `pkg-config` za prevajanje nativnih gemov, + - `libpq-dev` za gem `pg`, + - `libyaml-dev` za gem `psych`, + - `git` za geme, nameščene iz Git repozitorijev, + - `postgresql-client-` za `rails dbconsole` in `db:schema:dump` v formatu SQL. +- **Klient PostgreSQL je iz uradnega repozitorija PGDG** (apt.postgresql.org), ne iz Debiana. Debian ima navadno starejšo glavno različico, `pg_dump` pa zavrne izvoz iz novejšega strežnika. Različico za strežnik (`postgres:`) in klient določa ena spremenljivka `PG_MAJOR` v `.env` (privzeto 18). Compose jo preda Dockerfile kot build argument. Po spremembi `PG_MAJOR` zgradi sliko znova (`docker compose build`). Pri prehodu na novo glavno različico strežnika obstoječi podatki v volumnu `pgdata` niso združljivi, zato jih je treba izvoziti in uvoziti (ali volume izbrisati). +- **Geme hrani volume `bundle`**, ki je priklopljen na `/usr/local/bundle`. To je `GEM_HOME` uradne Ruby slike in je že v `PATH`. `gem install` in `bundle install` zato pišeta v isto mapo, gemi pa se ohranijo med zagoni kontejnerja. +- **`BUNDLE_PATH` namenoma ni nastavljen.** Z njim bi `bundle install` geme nameščal v drugo mapo kot `gem install`, izvršljive datoteke (`rails`, `rake`) pa ne bi bile v `PATH`. +- **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 z `id -u`), ga spremeni v `Dockerfile` in v `docker-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 po `docker compose down`. + +## Nov projekt iz predloge + +### 1. Kopiraj predlogo + +```bash +git clone moj-projekt +cd moj-projekt +rm -rf .git && git init +``` + +### 2. Nastavi okoljske spremenljivke + +```bash +cp .env.example .env +``` + +V `.env` vpiši ime baze, uporabnika in geslo. `APP_DATABASE_HOST` naj ostane `db` (ime servisa v Compose). + +### 3. Zgradi sliko in namesti Rails + +```bash +docker compose build +docker compose run --rm app gem install rails +``` + +### 4. Ustvari Rails aplikacijo + +```bash +docker compose run --rm app rails new . --database=postgresql --skip-docker +``` + +- `--skip-docker` prepreči, da bi Rails ustvaril svoj (produkcijski) `Dockerfile` in prepisal obstoječega. +- Ko vpraša, ali naj prepiše `.gitignore`, odgovori `n`. Če želiš, iz Rails-ove različice ročno dodaj manjkajoče vrstice. +- Ko vpraša, ali naj prepiše `README.md`, odgovori `n`, sicer izgubiš ta navodila. Navodila za aplikacijo lahko pozneje dopišeš sem. + +### 5. Poveži Rails z bazo + +V `config/database.yml` razdelek `development` nastavi na okoljske spremenljivke: + +```yaml +development: + <<: *default + database: <%= ENV["APP_DATABASE"] %> + host: <%= ENV["APP_DATABASE_HOST"] %> + port: <%= ENV["APP_DATABASE_PORT"] %> + username: <%= ENV["APP_DATABASE_USERNAME"] %> + password: <%= ENV["APP_DATABASE_PASSWORD"] %> +``` + +Razdelek `test` nastavi enako, le z drugim imenom baze (npr. `<%= ENV["APP_DATABASE"] %>_test`). + +### 6. Ustvari bazo in zaženi aplikacijo + +```bash +docker compose run --rm app bin/rails db:prepare +docker compose up +``` + +Aplikacija je dosegljiva na . + +### 7. Odkomentiraj namestitev gemov v Dockerfile + +Ko obstajata `Gemfile` in `Gemfile.lock`, v `Dockerfile` odkomentiraj: + +```dockerfile +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 ` | +| 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 + +```bash +docker compose run --rm app bundle add +``` + +Po ročni spremembi `Gemfile`: + +```bash +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`, `rollup` ali `webpack` (jsbundling-rails), +- `--css=bootstrap`, `bulma`, `postcss` ali `sass` (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`): + +```dockerfile +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: + +```bash +docker compose down +docker volume ls # poišči _bundle +docker volume rm _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`). Ob prvem zagonu PostgreSQL potrebuje nekaj sekund za inicializacijo, zato ukaz po potrebi ponovi. + +**`A server is already running`** +Ostala je datoteka s PID-om strežnika: + +```bash +rm tmp/pids/server.pid +``` + +**Ponastavitev baze od začetka** + +```bash +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. +- `.env` nikoli ne shranjuj v Git. V repozitorij gre samo `.env.example`. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..576565c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +services: + app: + user: "1000:1000" + build: + context: . + dockerfile: Dockerfile + args: + PG_MAJOR: ${PG_MAJOR:-18} + command: bin/rails server -b 0.0.0.0 -p 3000 + ports: + - "3000:3000" + env_file: .env + environment: + RAILS_ENV: development + APP_DATABASE: ${APP_DATABASE} + APP_DATABASE_HOST: ${APP_DATABASE_HOST} + APP_DATABASE_PORT: ${APP_DATABASE_PORT} + APP_DATABASE_USERNAME: ${APP_DATABASE_USERNAME} + APP_DATABASE_PASSWORD: ${APP_DATABASE_PASSWORD} + volumes: + - .:/app + - bundle:/usr/local/bundle + depends_on: + - db + + db: + image: postgres:${PG_MAJOR:-18} + environment: + POSTGRES_DB: ${APP_DATABASE} + POSTGRES_USER: ${APP_DATABASE_USERNAME} + POSTGRES_PASSWORD: ${APP_DATABASE_PASSWORD} + volumes: + - pgdata:/var/lib/postgresql/data + +volumes: + pgdata: + bundle: