Podman (docker) RUN script image build

Fórumok

Üdv,

Egy image buildelésekor szeretnék létrehozni egy mariadb adatbázist (van is rá egy dbscript.sh scriptem). Hogyan érdemes ezt a Dockerfile-be beírni?

Valahogy el kellene indítani a mariadbd-t, hogy a script lefuttatható legyen.

# Dockerfile
# ....

RUN mariadb-install-db
RUN /usr/sbin/mariadbd -u root               # <-- előtérben fut, nem megy tovább a következő lépésre
RUN /tmp/dbscript.sh mydbname username password

# ...
ENTRYPOINT /usr/bin/supervisord -c /etc/supervisord.conf

Háttérben kellene indítani a mariadbd-t, mert addig nem megy tovább. Az elegáns, helyes megoldást keresem.

 

Van ötletetek?

Hozzászólások

Image buildkor nem elegáns db-t létrehozni, sőt a db imaget csak használni kell, nem kell rebuildelni. Hozza létre az app, az induláskor, ha még nem létezik.

Én a command parancsba szoktam tenni az applikációt futtató konténerbe (a példában mysql és docker-compose.yml van).
Nem mondom hogy ez a legjobb megoldás. A mysql jelszót berakhatod egy mysql.ini fájlba is az /etc alatt és akkor nem figyelmeztet.

command: sh -c 'mysql -u root --password=${MYSQL_ROOT_PASSWORD} -h mysql < /app/initdb.sql && /app/start.sh'

Így persze fel kell telepítened az application image-be a "mariadb-client"-et, de minden indulás során lefut és a DB imaged maradhat official.
FONTOS, hogy az SQL-ben mindent IF-elj mindenhol, hogy csak akkor csinálja meg a műveleteket ha még nem léteznek.

CREATE DATABASE IF NOT EXISTS ...
CREATE USER IF NOT EXISTS ...
FLUSH PRIVILEGES;

sry ha hülyeség, kezdő dockeres vagyok, de nem erre van a /docker-entrypoint-initdb.d/? 

Ha nem az official dbt használod, akkor lesd el onnan az entrypoint scriptet, valszeg ez az: https://github.com/MariaDB/mariadb-docker/blob/master/docker-entrypoint…

(vagy ha nem akarsz GPL liszenszinget, akkor írj egy saját entrypoint scriptet, ami felnyalja startupkor a volumeodból a shell scriptedet) 

Ne keverd össze a konténert a VM-mel/chroot-tal hasonlókkal - ugyanis nagyon más. A konténer _csak_ a DB-szerver funkciót valósítsa meg, a DB-t (mint perzisztens tartalmat) ne a konténer építése, hanem az azt használó alkalmazás indulása hozza létre, ha még nem létezik.

Miért hoznál létre db-t? Az egy másik konténer, csatolt erőforrás.

De ehhez egy másik konténer való. Van egy konténered, az alkalmazás, ami használja a db-t, és egy másik konténered, ami maga a db.

Szépen elkülöníted a felelősségi köröket, nem keverednek a konténerek között.

Használd például a hivatalos mariadb konténert.

https://hub.docker.com/_/mariadb/

Initializing a fresh instance

When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh.sql.sql.gz.sql.xz and .sql.zst that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. .sh files without file execute permission are sourced rather than executed. You can easily populate your mariadb services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MARIADB_DATABASE / MYSQL_DATABASE variable.

Azaz van egy maradb konténered, a neki megfelelő init scripttel a /docker-entrypoint-initdb.d mappa alatt. Ehhez persze a legcélszerűbb egy custom image, ami a mariadb image-ből ered, és ADD-dal vagy COPY-val hozzáadod az init scriptedet. Ezután lesz egy image-d, amit ha elindítasz üresen, létrehozza azt az adatbázist, amit szeretnél. Ezután már csatlakozhatsz az alkalmazásból hozzá.

Igen, lehet így is - de ez attól még erősen antipattern, hiszen a DB-szerver felhúzása az egy feladat, a DB-szerverben az adott alkalmazásnak a séma/user/adatszerkezet/ősfeltöltés meg egy másik - célszerűen az alkalmazásra bízva - a DB-szerveren maximum egy "create user pistikeapp..." legyen induláskor - a többit meg csinálja meg az alkalmazás (célszerűen flyway, liquibase vagy hasonló támogatással, ahogy illik)

A flyway/liquibase és hasonlók sok mindent nem tudnak, például nem tudnak DB konfigurációt változtatni, stb. Valamint valakinek létre is kell hoznia, és megfelelő jogokkal ellátnia azt a usert, aki az adatbázishoz hozzáfér. A mariadb környezeti változói által adott lehetőségek ehhez kevesek, a default konfig is sok esetben haszontalan. Konfigot meg nem tud változtatni egyik séma menedzser eszköz sem. Megvan mindkettőnek a helye: custom image a custom konfigurációhoz, a séma menedzser meg menedzselje a sémát, ahogy kell. Mindkettőnek más a feladatköre.

Attól még nem kéne gányolni... Gondolom, a tesztkörnyezetben majd az alkalmazás "késznek" veszi a DB-t, aztán "úgy marad" az élesben is - yool begyógyítva ezt az antipattern megoldást. (Mivel a DB-install/startup az egyszer van, DB/séma kreálás meg lehet n+1-szer is, hiszen kvázi tetszőleges számú DB-t/sémát létre lehet MySQL-ben is hozni - miközben a konténert buildelni nem kell n+1-szer.

Buildkor nem szep megoldas DB-t letrehozni, azt runtime kell.

A gyari image tudja ezt, olvasd el a doksijat milyen kornyezeti valtozokat kezel:
https://hub.docker.com/_/mariadb

Jelen esetben neked erre van szukseged:

MARIADB_DATABASE / MYSQL_DATABASE

This variable allows you to specify the name of a database to be created on image startup.

Én így oldottam meg, ez a docker-compose.yml:

version: "2"

volumes:
  DB:

services:
  appneve:
    container_name: appneve
    image: appneve:latest
    volumes:
      - /opt/appneve/www:/var/www
    ports:
      - 1099:80
    restart: always
    links:
      - appneve_db

  appneve_db:
    container_name: appneve_db
    image: mariadb:10.6
    volumes:
      - DB:/var/lib/mysql
      - /opt/appneve/conf/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=rootjelszo
      - MYSQL_DATABASE=appneve
      - MYSQL_USER=appneve
      - MYSQL_PASSWORD=appjelszava

 

Első indításkor betölti az /opt/appneve/conf/schema.sql fájlt az appneve adatbázisba, és azonnal használható lesz az appod.