====== Podman ====== Kilka przykładów tworzenia kontenerów. **Pamiętać, że nie trzeba być rootem, ani sudo do niczego.** $ cat /etc/hosts [...] 127.0.0.1 strona.ping.local php.ping.local [...] ==== Apache ==== Katalog z kontenerem. $ cd apache $ tree . ├── conf │   ├── 00-security.conf │   ├── 01-logformat.conf │   ├── 02-servername.conf │   └── 99-strona.ping.local.conf ├── Dockerfile ├── log └── public_html └── index.html Zawartość plików konfiguracyjnych w katalogu conf: $ cat conf/00-bezpieczenstwo.conf Header always set X-Content-Type-Options nosniff Header always set X-Frame-Options "SAMEORIGIN" Header set X-XSS-Protection "1; mode=block" Servertokens Prod ServerSignature Off Zakładam, że strona będzie za jakimś rodzajem proxy, a chcę widzieć w logach adresy IP odwiedzających. $ cat conf/01-logformat.conf LogFormat "%v %{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" nginxproxy Apache pokazuje w logach brak ustawionego ServerName, więc jakiś tam zawsze ustawiam. $ cat conf/02-servername.conf ServerName strona.ping.local Prosty vhost: $ cat conf/99-strona.ping.local.conf ServerName strona.ping.local:8080 ServerAlias *.strona.ping.local DocumentRoot /var/www/html CustomLog logs/strona-access.log nginxproxy ErrorLog logs/strona-errors.log AllowOverride All Require all granted Plik do budowania obrazu: $ cat Dockerfile from registry.redhat.io/ubi9/httpd-24:1-331.1722518952 ADD conf/* /etc/httpd/conf.d/ USER 48 CMD run-httpd Logowanie do Red Hata: $ podman login registry.redhat.io Username: [login do redhat.com] Password: [hasło do redhat.com] Budowanie obrazu: $ podman build -t strona-apache . STEP 1/4: FROM registry.redhat.io/ubi9/httpd-24:1-331.1722518952 Trying to pull registry.redhat.io/ubi9/httpd-24:1-331.1722518952... Getting image source signatures Checking if image destination supports signatures Copying blob aa3367aaf4aa done | Copying blob cc296d75b612 done | Copying blob db22e630b1c7 done | Copying config e19a3fc93d done | Writing manifest to image destination Storing signatures STEP 2/4: ADD conf/* /etc/httpd/conf.d/ --> [identyfikator] STEP 3/4: USER 48 --> [identyfikator] STEP 4/4: CMD run-httpd COMMIT strona-apache --> 28baafdb39f5 Successfully tagged localhost/strona-apache:latest [dlugi_śmieszny_numer] Uprawnia do katalogów log oraz public_html: $ podman unshare chown -R 48:48 log/ $ podman unshare chown -R 48:48 public_html/ Uruchomienie kontenera. W tym wypadku Apache nie będzie mógł modyfikować zawartości katalogu /var/www/html. Ta kropkaukośnik jest ważna. Bez niej nie zadziała montowanie woluminów. $ podman run -d -p 8801:8080 -v ./log:/var/log/httpd:Z,rw -v ./public_html:/var/www/html:Z,ro strona-apache $ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [identyfikator] localhost/strona-apache:latest /bin/sh -c run-ht... 32 minutes ago Up 32 minutes 0.0.0.0:8801->8080/tcp, 8080/tcp, 8443/tcp [śmieszna_nazwa] I już działa. $ curl -Isk strona.ping.local:8801 HTTP/1.1 200 OK [...] ==== MariaDB ==== $ cd mariadb tree . . ├── conf │   └── 99-baza.cnf ├── database ├── Dockerfile └── log Konfiguracja w pliku cnf: $ cat conf/99-baza.cnf [mariadb] log_output=FILE general_log general_log_file=/var/log/mariadb/general.log slow_query_log slow_query_log_file=/var/log/mariadb/slow.log Dockerfile: $ cat Dockerfile from registry.redhat.io/rhel9/mariadb-105:1-194 ADD conf/* /etc/my.cnf.d/ USER 27 CMD ["run-mysqld"] Budowanie obrazu: $ podman build -t baza . Uprawnienia katalogów: $ podman unshare chown -R 27:27 log/ $ podman unshare chown -R 27:27 database/ Skomplikowane uruchomienie kontenera: $ podman run -d -e MYSQL_ROOT_PASSWORD=TajneHaslo -e MYSQL_USER=uzytkownik -e MYSQL_PASSWORD=InneHaslo -e MYSQL_DATABASE=nazwabazy -v ./database:/var/lib/mysql:Z,rw -v ./log:/var/log/mariadb:Z,rw -p 5301:3306 baza Wyjaśnienie parametrów: * MYSQL_ROOT_PASSWORD - hasło roota, niepraktyczne i niepotrzebne, ale warto jakieś podać, * MYSQL_USER - nazwa użytkownika aplikacyjnego, * MYSQL_PASSWORD - hasło użytkownika aplikacyjnego, * MYSQL_DATABASE - nazwa bazy danych, której używa powyższy użytkownik. Jeżeli na woluminie zamontowanym w katalogu datadir jest już jakaś baza danych, powyższe zmienne nie działają. Można później zmienić hasła użytkowników narzędziami bazodanowymi. ==== PHP ==== $ cd php tree -a . . ├── conf │   ├── apache │   │   ├── 00-bezpieczenstwo.conf │   │   ├── 01-logformat.conf │   │   ├── 02-servername.conf │   │   └── 99-php.ping.local.conf │   └── php │   └── 99-var.ini ├── Dockerfile ├── log │   ├── php-access.log │   └── php-errors.log ├── public_html │   └── info.php └── sessions Pliki konfiguracyjne Apache są podobne do tych z poprzedniego przykładu. Różni się tylko nazwa vhosta oraz nazwy plików w logami. Dockerfile: $ cat Dockerfile from registry.redhat.io/ubi9/php-82:1-21.1724040036 ADD conf/apache/* /etc/httpd/conf.d/ ADD conf/php/* /etc/php.d/ USER 1001 CMD /usr/libexec/s2i/run Konfiguracja PHP: $ cat 99-var.ini [PHP] expose_php = Off memory_limit = 128M post_max_size = 64M upload_max_filesize = 64M [Date] date.timezone = Europe/Warsaw Uprawnienia: $ podman unshare chown -R 1001:1001 log/ public_html/ sessions/ Uruchomienie kontenera: $ podman run -d -v ./public_html/:/var/www/html:Z -v ./sessions:/tmp/sessions:Z -v ./log:/var/log/httpd:Z -p 8888:8080 baszarek-php82:latest ==== Uruchomienie kontenerów z systemd ==== $ mkdir -p ~/.config/systemd/user $ cd ~/.config/systemd/user $ podman generate systemd --name smieszna-nazwa --files --new $ systemctl --user enable container-smieszna-nazwa $ podman stop smieszna-nazwa $ systemctl --user start container-smieszna-nazwa $ systemctl --user enable container-smieszna-nazwa ==== Konteneryzowanie małej aplikacji ==== Aplikacja została zmodyfikowana pod kontener. Usunąłem z niej pliki konfiguracyjne i zastąpiłem je zmiennymi środowiskowymi. Można używać obydwu, gdzie pliki przeważają zmienne. Obrazy MariaDB Red Hata takie właśnie są. Można ustawić różne zmienne regulujące dostęp do bazy danych, ale jeżeli ta już istnieje na woluminie, są one ignorowane. Dockerfile: from registry.access.redhat.com/ubi9/openjdk-17-runtime:1.20-2.1724037300 RUN mkdir -p /opt/astech ADD ./astech /opt/astech WORKDIR /opt/astech ENV AST_MM_VERSION="0.49.19.1" CMD ["/usr/bin/python3", "astech.py"] Pliki w katalogu z plikiem Dockerfile, to trzech poziomów: # tree -aL 3 . ├── astech │   ├── astech.py │   ├── bottle.py │   ├── error404.tpl │   ├── footer.tpl │   ├── gamefiles.tpl │   ├── header.tpl │   ├── index.tpl │   ├── login.tpl │   ├── megamek-0.49.19.1 │   │   ├── data │   │   ├── docs │   │   ├── lib │   │   ├── logs │   │   ├── MegaMek.jar │   │   ├── mm │   │   ├── mm.bat │   │   ├── mmconf │   │   ├── savegames │   │   └── userdata │   ├── options.tpl │   └── static │   ├── astech_logo.png │   ├── delete.png │   ├── download.png │   ├── selected.png │   ├── select.png │   ├── server_off.png │   ├── server_on.png │   └── style.css ├── boards ├── Dockerfile ├── logs │   ├── megameklab.log │   ├── megamek.log │   └── mekhq.log ├── mechfiles └── savegames Budowanie obrazu: podman build -t astech049191 . Uprawnienia do woluminów. Domyślnie aplikacja w podmanie uruchamia się z uprawnieniami użytkownika o UID 1001, ale można to zmienić w Dockerfile, lub parametrem //-u// przy //podman run//. $ podman unshare chown -R 1001 boards/ logs/ mechfiles/ savegames/ $ podman unshare chmod 750 boards/ logs/ mechfiles/ savegames/ $ ll razem 8 drwxr-xr-x. 4 lukasz lukasz 4096 09-05 07:03 astech drwxr-x---. 2 524472 lukasz 34 09-05 07:30 boards -rw-r--r--. 1 lukasz lukasz 217 09-05 06:53 Dockerfile drwxr-x---. 2 524472 lukasz 64 09-05 07:28 logs drwxr-x---. 2 524472 lukasz 6 09-05 06:47 mechfiles drwxr-x---. 2 524472 lukasz 6 09-05 06:47 savegames Uruchomienie kontenera: $ podman run --name myastech -d -p 8080:8080 -p 2346:2346 -e AST_MM_PORT=2346 -e AST_USER=someuser -e AST_PASS=somepassword -v ./savegames:/opt/astech/megamek-0.49.19.1/savegames:rw,Z,U -v ./logs:/opt/astech/megamek-0.49.19.1/logs:rw,Z,U -v ./boards:/opt/astech/megamek-0.49.19.1/data/boards/astech:rw,Z,U -v ./mechfiles:/opt/astech/megamek-0.49.19.1/data/mechfiles/astech:rw,Z,U astech049191 ==== su - [uzytkownik] i xdg ==== "systemctl --user" nie będzie działał dobrze, dopóki użytkownik go wywołujący nie będzie zalogowany. Można to obejść na dwa sposoby: zalogować się przez "ssh [uzytkownik]@localhost", lub dopisując zmienną o wartości "/run/user[identyfikator_z_pliku_passwd] do pliku bashrc: # "systemctl --user " bez tego nie dziala XDG_RUNTIME_DIR=/run/user/3501 export XDG_RUNTIME_DIR ==== Import i wczytywanie obrazów ==== Kiedy nie chcę żadnego rejestru. $ podman image ls REPOSITORY TAG IMAGE ID CREATED SIZE localhost/astech-mm 0.49.19.1 6e01cf1442ce 26 hours ago 962 MB registry.access.redhat.com/ubi9/openjdk-17-runtime 1.20-2.1724037300 cf4676726e3f 2 weeks ago 368 MB $ podman save --quiet -o astech-mm-049191.tar 6e01cf1442ce Wczytywanie pliku //astech-mm-049191.tar// na innym hoście: $ podman load --quiet -i astech-mm-049191.tar $ podman image ls REPOSITORY TAG IMAGE ID CREATED SIZE 6e01cf1442ce 26 hours ago 962 MB $ podman tag 6e01cf1442ce astech:0.49.19.1 $ podman image ls REPOSITORY TAG IMAGE ID CREATED SIZE localhost/astech-mm 0.49.19.1 6e01cf1442ce 26 hours ago 962 MB ==== cannot change memory protections ==== Podczas uruchamiania kontenera pojawiają się błędy "error while loading shared libraries: [cośtam].so.[numer]: cannot change memory protections" $ podman info | grep 'graphRoot' graphRoot: /home/lukasz/.local/share/containers/storage graphRootAllocated: 482933219328 graphRootUsed: 214006886400 # semanage fcontext -a -t container_var_lib_t '/home/lukasz/.local/share/containers/storage(/.*)?' # restorecon -Rv /home/lukasz/.local/share/containers/ Źródło: https://access.redhat.com/solutions/7021610 ==== Connection reset by peer ==== Podman w werji 4.x nieprawidłowo mapuje porty, jeżeli: * aplikacja wystawia się na hoście 127.0.0.1 i porcie przykładowo 8080 * podman run jest uruchomiony z parametrem -p 0.0.0.0:8080:8080 i oczekuję, że aplikacja wystawi się na całą adresację IPv4. Aplikacja w kontenerze musi również słuchać na 0.0.0.0. Warto zostawić sobie do tego zmienną środowiskową, która będzie modyfikować działanie aplikacji. W podmanie 5.2.2 (który jest w dystrybucji Fedora 40) to działa już dobrze. Aplikacja może słuchać na lokalnym hoście, ale Podman może przemapować ten ruch na cały internet, lub wybrane podsieci. Źródło: https://github.com/containers/podman/issues/19602#issuecomment-1675709528