{"id":12873,"date":"2019-10-16T14:09:07","date_gmt":"2019-10-16T12:09:07","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/"},"modified":"2019-10-16T14:09:07","modified_gmt":"2019-10-16T12:09:07","slug":"creating-a-customized-postgresql-container-using-buildah","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/","title":{"rendered":"Creating a customized PostgreSQL container using buildah"},"content":{"rendered":"<p>Quite some time ago I blogged about how you could build your <a href=\"https:\/\/www.dbi-services.com\/blog\/how-we-build-our-customized-postgresql-docker-image\/\" target=\"_blank\" rel=\"noopener noreferrer\">customzized PostgreSQL container<\/a> by using a Dockerfile and <a href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/build\/\" target=\"_blank\" rel=\"noopener noreferrer\">Docker build<\/a>. In the meantime Red Hat replaced Docker in <a href=\"https:\/\/www.openshift.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">OpenShift<\/a> and SUSE replaced Docker as well in <a href=\"https:\/\/www.suse.com\/products\/caas-platform\/\" target=\"_blank\" rel=\"noopener noreferrer\">CaaS<\/a>. As a consequence there need to be other ways of building containers and one of them is <a href=\"https:\/\/buildah.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">buildah<\/a>. You can use buildah to build from a Docker file as well, but in this post we will use a simple bash script to create the container.<\/p>\n<p><!--more--><\/p>\n<p>We start be defining four variables that define PGDATA, the PostgreSQL major version, the full version string and the minor version which will be used to create our standard installation location (these will also go into the entrypoint, see below):<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n#!\/bin\/bash\n_PGDATA=\"\/u02\/pgdata\"\n_PGMAJOR=12\n_PGVERSION=12.0\n_PGMINOR=\"db_0\"\n<\/pre>\n<p>As mentioned in the beginning buildah will be used to create the container. For running the container we need something else, and that is <a href=\"https:\/\/podman.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">podman<\/a>. You can run the container buildah creates with plain Docker as well, if you want, as it is <a href=\"https:\/\/github.com\/opencontainers\/image-spec\" target=\"_blank\" rel=\"noopener noreferrer\">oci compliant<\/a> but as Red Hat does not ship Docker anymore we will use the recommended way of doing it by using podman. So the natural next step in the script is do install buildah and podman:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\ndnf install -y buildah podman\n<\/pre>\n<p>Buildah can create containers from scratch, which means you start with a container that contains nothing except some meta data:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nnewcontainer=$(buildah from scratch)\n<\/pre>\n<p>Once we have the new scratch container it gets mounted so <a href=\"https:\/\/en.wikipedia.org\/wiki\/DNF_(software)\" target=\"_blank\" rel=\"noopener noreferrer\">dnf<\/a> can be used to install the packages we need into the container without actually using dnf in the container:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nscratchmnt=$(buildah mount $newcontainer)\nls -la $scratchmnt\ndnf install --installroot $scratchmnt --releasever 8 bash coreutils gcc openldap-devel platform-python-devel readline-devel bison flex perl-ExtUtils-Embed zlib-devel openssl-devel pam-devel libxml2-devel libxslt-devel bzip2 wget policycoreutils-python-utils make tar --setopt install_weak_deps=false --setopt=tsflags=nodocs --setopt=override_install_langs=en_US.utf8 -y\n<\/pre>\n<p>Using &#8220;buildah config&#8221; the container can be configured. Here it is about the author, environment variables, the default user and the entrypoint that will be used once the conatiner will be started:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nbuildah config --created-by \"dbi services\"  $newcontainer\nbuildah config --author \"dbi services\" --label name=dbiservices $newcontainer\nbuildah run $newcontainer groupadd postgres\nbuildah run $newcontainer useradd -g postgres -m postgres\nbuildah config --user postgres $newcontainer\nbuildah config --workingdir \/home\/postgres $newcontainer\nbuildah config --env PGDATABASE=\"\" $newcontainer\nbuildah config --env PGUSERNAME=\"\" $newcontainer\nbuildah config --env PGPASSWORD=\"\" $newcontainer\nbuildah config --env PGDATA=${_PGDATA} $newcontainer\nbuildah config --env PGMAJOR=${_PGMAJOR} $newcontainer\nbuildah config --env PGMINOR=${_PGMINOR} $newcontainer\nbuildah config --env PGVERSION=${_PGVERSION} $newcontainer\nbuildah config --entrypoint \/usr\/bin\/entrypoint.sh $newcontainer\nbuildah copy $newcontainer .\/entrypoint.sh \/usr\/bin\/entrypoint.sh\nbuildah run $newcontainer chmod +x \/usr\/bin\/entrypoint.sh\n<\/pre>\n<p>What follows is basically installing PostgreSQL from source code:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nbuildah run --user root $newcontainer mkdir -p \/u01 \/u02\nbuildah run --user root $newcontainer chown postgres:postgres \/u01 \/u02\nbuildah run --user postgres $newcontainer wget https:\/\/ftp.postgresql.org\/pub\/source\/v${_PGVERSION}\/postgresql-${_PGVERSION}.tar.bz2 -O \/home\/postgres\/postgresql-${_PGVERSION}.tar.bz2\nbuildah run --user postgres $newcontainer \/usr\/bin\/bunzip2 \/home\/postgres\/postgresql-${_PGVERSION}.tar.bz2\nbuildah run --user postgres $newcontainer \/usr\/bin\/tar -xvf \/home\/postgres\/postgresql-${_PGVERSION}.tar -C \/home\/postgres\/\nbuildah run --user postgres $newcontainer \/home\/postgres\/postgresql-12.0\/configure --prefix=\/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR} --exec-prefix=\/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR} --bindir=\/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin --libdir=\/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/lib --includedir=\/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/include \nbuildah run --user postgres $newcontainer \/usr\/bin\/make -C \/home\/postgres all\nbuildah run --user postgres $newcontainer \/usr\/bin\/make -C \/home\/postgres install\nbuildah run --user postgres $newcontainer \/usr\/bin\/make -C \/home\/postgres\/contrib install\n<\/pre>\n<p>Containers shoud be as small as possible so lets do some cleanup:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/postgresql-${_PGVERSION}.tar\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/config\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/config.log\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/config.status\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/contrib\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/GNUmakefile\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/postgresql-12.0\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/src\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/doc\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/Makefile\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/home\/postgres\/.wget-hsts\n<\/pre>\n<p>When you want to run PostgreSQL inside a container you do not need any of the following binaries, so these can be cleaned as well:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/vacuumlo\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/vacuumdb\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/reindexdb\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pgbench\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_waldump\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_test_timing\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_test_fsync\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_standby\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_restore\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_recvlogical\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_receivewal\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_isready\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_dumpall\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_dump\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_checksums\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_basebackup\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/pg_archivecleanup\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/oid2name\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/dropuser\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/dropdb\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/createuser\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/createdb\nbuildah run --user postgres $newcontainer \/usr\/bin\/rm -rf \/u01\/app\/postgres\/product\/${_PGMAJOR}\/${_PGMINOR}\/bin\/clusterdb\n<\/pre>\n<p>Last, but not least remove all the packages we do not require anymore and get rid of the dnf cache:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\ndnf remove --installroot $scratchmnt --releasever 8 gcc openldap-devel readline-devel bison flex perl-ExtUtils-Embed zlib-devel openssl-devel pam-devel libxml2-devel libxslt-devel bzip2 wget policycoreutils-python-utils make tar -y\ndnf clean all -y --installroot $scratchmnt --releasever 8\n# Clean up yum cache\nif [ -d \"${scratchmnt}\" ]; then\nrm -rf \"${scratchmnt}\"\/var\/cache\/yum\nfi\nbuildah unmount $newcontainer\n<\/pre>\n<p>Ready to publish the container:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nbuildah commit $newcontainer dbi-postgres\n<\/pre>\n<p>When you put all those steps into a script and run that you should see the just created container:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n[root@doag2019 ~]$ buildah containers\nCONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME\n47946e4b4fc8     *                  scratch                          working-container\n[root@doag2019 ~]$\n<\/pre>\n<p>&#8230; but now we also have a new image that can be started:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\nIMAGE NAME                                               IMAGE TAG            IMAGE ID             CREATED AT             SIZE\nlocalhost\/dbi-postgres                                   latest               dfcd3e8d5273         Oct 13, 2019 13:22     461 MB\n<\/pre>\n<p>Once we start that the entrypoint will be executed:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n#!\/bin\/bash\n# this are the environment variables which need to be set\nPGDATA=${PGDATA}\/${PGMAJOR}\nPGHOME=\"\/u01\/app\/postgres\/product\/${PGMAJOR}\/${PGMINOR}\"\nPGAUTOCONF=${PGDATA}\/postgresql.auto.conf\nPGHBACONF=${PGDATA}\/pg_hba.conf\nPGDATABASENAME=${PGDATABASE}\nPGUSERNAME=${PGUSERNAME}\nPGPASSWD=${PGPASSWORD}\n# create the database and the user\n_pg_create_database_and_user()\n{\n${PGHOME}\/bin\/psql -c \"create user ${PGUSERNAME} with login password '${PGPASSWD}'\" postgres\n${PGHOME}\/bin\/psql -c \"create database ${PGDATABASENAME} with owner = ${PGUSERNAME}\" postgres\n${PGHOME}\/bin\/psql -c \"create extension pg_stat_statements\" postgres\n}\n# start the PostgreSQL instance\n_pg_prestart()\n{\n${PGHOME}\/bin\/pg_ctl -D ${PGDATA} -w start\n}\n# Start PostgreSQL without detaching \n_pg_start()\n{\nexec ${PGHOME}\/bin\/postgres \"-D\" \"${PGDATA}\"\n}\n# stop the PostgreSQL instance\n_pg_stop()\n{\n${PGHOME}\/bin\/pg_ctl -D ${PGDATA} stop -m fast\n}\n# initdb a new cluster\n_pg_initdb()\n{\n${PGHOME}\/bin\/initdb -D ${PGDATA} --data-checksums\n}\n# adjust the postgresql parameters\n_pg_adjust_config() {\nif [ -z $PGMEMORY ]; then MEM=\"128MB\"\nelse                      MEM=$PGMEMORY; fi\n# PostgreSQL parameters\necho \"shared_buffers='$MEM'\" &gt;&gt; ${PGAUTOCONF}\necho \"effective_cache_size='128MB'\" &gt;&gt; ${PGAUTOCONF}\necho \"listen_addresses = '*'\" &gt;&gt; ${PGAUTOCONF}\necho \"logging_collector = 'off'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_truncate_on_rotation = 'on'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_line_prefix = '%m - %l - %p - %h - %u@%d '\" &gt;&gt; ${PGAUTOCONF}\necho \"log_directory = 'pg_log'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_min_messages = 'WARNING'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_autovacuum_min_duration = '60s'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_min_error_statement = 'NOTICE'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_min_duration_statement = '30s'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_checkpoints = 'on'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_statement = 'none'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_lock_waits = 'on'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_temp_files = '0'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_timezone = 'Europe\/Zurich'\" &gt;&gt; ${PGAUTOCONF}\necho \"log_connections=on\" &gt;&gt; ${PGAUTOCONF}\necho \"log_disconnections=on\" &gt;&gt; ${PGAUTOCONF}\necho \"log_duration=off\" &gt;&gt; ${PGAUTOCONF}\necho \"client_min_messages = 'WARNING'\" &gt;&gt; ${PGAUTOCONF}\necho \"wal_level = 'replica'\" &gt;&gt; ${PGAUTOCONF}\necho \"wal_compression=on\" &gt;&gt; ${PGAUTOCONF}\necho \"max_replication_slots=20\" &gt;&gt; ${PGAUTOCONF}\necho \"max_wal_senders=20\" &gt;&gt; ${PGAUTOCONF}\necho \"hot_standby_feedback = 'on'\" &gt;&gt; ${PGAUTOCONF}\necho \"cluster_name = '${PGDATABASENAME}'\" &gt;&gt; ${PGAUTOCONF}\necho \"max_replication_slots = '10'\" &gt;&gt; ${PGAUTOCONF}\necho \"work_mem=8MB\" &gt;&gt; ${PGAUTOCONF}\necho \"maintenance_work_mem=64MB\" &gt;&gt; ${PGAUTOCONF}\necho \"shared_preload_libraries='pg_stat_statements'\" &gt;&gt; ${PGAUTOCONF}\necho \"autovacuum_max_workers=6\" &gt;&gt; ${PGAUTOCONF}\necho \"autovacuum_vacuum_scale_factor=0.1\" &gt;&gt; ${PGAUTOCONF}\necho \"autovacuum_vacuum_threshold=50\" &gt;&gt; ${PGAUTOCONF}\necho \"archive_mode=on\" &gt;&gt; ${PGAUTOCONF}\necho \"archive_command='\/bin\/true'\" &gt;&gt; ${PGAUTOCONF}\n# Authentication settings in pg_hba.conf\necho \"host    all             all             0.0.0.0\/0            md5\"  &gt;&gt; ${PGHBACONF}\n}\n# initialize and start a new cluster\n_pg_init_and_start()\n{\n# initialize a new cluster\n_pg_initdb\n# set params and access permissions\n_pg_adjust_config\n# start the new cluster\n_pg_prestart\n# set username and password\n_pg_create_database_and_user\n# restart database with correct pid\n_pg_stop\n_pg_start\n}\n# check if $PGDATA exists\nif [ -e ${PGDATA} ]; then\n# when $PGDATA exists we need to check if there are files\n# because when there are files we do not want to initdb\nif [ -e \"${DEBUG}\" ]; then\n\/bin\/bash\nelif [ -e \"${PGDATA}\/base\" ]; then\n# when there is the base directory this\n# probably is a valid PostgreSQL cluster\n# so we just start it\n_pg_start\nelse\n# when there is no base directory then we\n# should be able to initialize a new cluster\n# and then start it\n_pg_init_and_start\nfi\nelse\n# create PGDATA\nmkdir -p ${PGDATA}\n# initialze and start the new cluster\n_pg_init_and_start\nfi\n<\/pre>\n<p>Starting that up using podman:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n[root@doag2019 ~]$ podman run -e PGDATABASE=test -e PGUSERNAME=test -e PGPASSWORD=test --detach -p 5432:5432 localhost\/dbi-postgres\nf933df8216de83b3c2243860ace02f231748a05273c16d3ddb0308231004552f\nCONTAINER ID  IMAGE                          COMMAND               CREATED             STATUS             PORTS                   NAMES\nf933df8216de  localhost\/dbi-postgres:latest  \/bin\/sh -c \/usr\/b...  About a minute ago  Up 59 seconds ago  0.0.0.0:5432-&gt;5432\/tcp  nervous_leavitt\n<\/pre>\n<p>&#8230; and connecting from the host system:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n[root@doag2019 ~]$ psql -p 5432 -h localhost -U test test\nPassword for user test:\npsql (10.6, server 12.0)\nWARNING: psql major version 10, server major version 12.\nSome psql features might not work.\nType \"help\" for help.\ntest=&gt; select version();\nversion\n--------------------------------------------------------------------------------------------------------\nPostgreSQL 12.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.2.1 20180905 (Red Hat 8.2.1-3), 64-bit\n(1 row)\ntest=&gt; q\n<\/pre>\n<p>One you have that scripted and ready it is a very convinient way for creating images. What I like most is, that you can make changes afterwards without starting from scratch:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n[root@doag2019 ~]$ podman inspect localhost\/dbi-postgres\n[\n{\n\"Id\": \"dfcd3e8d5273116e5678806dfe7bbf3ca2276549db73e62f27b967673df8084c\",\n\"Digest\": \"sha256:b2d65e569becafbe64e8bcb6d49b065188411f596c04dea2cf335f677e2db68e\",\n\"RepoTags\": [\n\"localhost\/dbi-postgres:latest\"\n],\n\"RepoDigests\": [\n\"localhost\/dbi-postgres@sha256:b2d65e569becafbe64e8bcb6d49b065188411f596c04dea2cf335f677e2db68e\"\n],\n\"Parent\": \"\",\n\"Comment\": \"\",\n\"Created\": \"2019-10-13T11:22:15.096957689Z\",\n\"Config\": {\n\"User\": \"postgres\",\n\"Env\": [\n\"PGDATABASE=\",\n\"PGUSERNAME=\",\n\"PGPASSWORD=\",\n\"PGDATA=\/u02\/pgdata\",\n\"PGMAJOR=12\",\n\"PGMINOR=db_0\",\n\"PGVERSION=12.0\"\n],\n\"Entrypoint\": [\n\"\/bin\/sh\",\n\"-c\",\n\"\/usr\/bin\/entrypoint.sh\"\n],\n\"WorkingDir\": \"\/home\/postgres\",\n\"Labels\": {\n\"name\": \"dbiservices\"\n}\n},\n\"Version\": \"\",\n\"Author\": \"dbiservices\",\n\"Architecture\": \"amd64\",\n\"Os\": \"linux\",\n\"Size\": 460805033,\n\"VirtualSize\": 460805033,\n\"GraphDriver\": {\n\"Name\": \"overlay\",\n\"Data\": {\n\"MergedDir\": \"\/var\/lib\/containers\/storage\/overlay\/89de699f19781bb61eec12cf61a097a9daa31d7725fc3c078c76d0d6291cb074\/merged\",\n\"UpperDir\": \"\/var\/lib\/containers\/storage\/overlay\/89de699f19781bb61eec12cf61a097a9daa31d7725fc3c078c76d0d6291cb074\/diff\",\n\"WorkDir\": \"\/var\/lib\/containers\/storage\/overlay\/89de699f19781bb61eec12cf61a097a9daa31d7725fc3c078c76d0d6291cb074\/work\"\n}\n},\n\"RootFS\": {\n\"Type\": \"layers\",\n\"Layers\": [\n\"sha256:89de699f19781bb61eec12cf61a097a9daa31d7725fc3c078c76d0d6291cb074\"\n]\n},\n\"Labels\": {\n\"name\": \"dbiservices\"\n},\n\"Annotations\": {},\n\"ManifestType\": \"application\/vnd.oci.image.manifest.v1+json\",\n\"User\": \"postgres\",\n\"History\": [\n{\n\"created\": \"2019-10-13T11:22:15.096957689Z\",\n\"created_by\": \"dbi services\",\n\"author\": \"dbiservices\"\n}\n]\n}\n]\n<\/pre>\n<p>Assume we want to add a new environment variable. All we need to do is this:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n[root@doag2019 ~]$ buildah containers\nCONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME\n47946e4b4fc8     *                  scratch                          working-container\n[root@doag2019 ~]$ buildah config --env XXXXXXX=\"xxxxxxxx\" 47946e4b4fc8\n[root@doag2019 ~]$ buildah commit 47946e4b4fc8 dbi-postgres\nGetting image source signatures\nSkipping fetch of repeat blob sha256:9b74f2770486cdb56539b4a112b95ad7e10aced3a2213d33878f8fd736b5c684\nCopying config sha256:e2db86571bfa2e64e6079077fe023e38a07544ccda529ba1c3bfc04984f2ac74\n606 B \/ 606 B [============================================================] 0s\nWriting manifest to image destination\nStoring signatures\ne2db86571bfa2e64e6079077fe023e38a07544ccda529ba1c3bfc04984f2ac74\n<\/pre>\n<p>The new image with the new variable is ready:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">\n[root@doag2019 ~]$ buildah images\nIMAGE NAME                                               IMAGE TAG            IMAGE ID             CREATED AT             SIZE\n                                                                              dfcd3e8d5273         Oct 13, 2019 13:22     461 MB\nlocalhost\/dbi-postgres                                   latest               e2db86571bfa         Oct 13, 2019 13:52     461 MB\n[root@doag2019 ~]$ buildah inspect localhost\/dbi-postgres\n...\n\"Env\": [\n\"PGDATABASE=\",\n\"PGUSERNAME=\",\n\"PGPASSWORD=\",\n\"PGDATA=\/u02\/pgdata\",\n\"PGMAJOR=12\",\n\"PGMINOR=db_0\",\n\"PGVERSION=12.0\",\n\"XXXXXXX=xxxxxxxx\"\n],\n...\n<\/pre>\n<p>Nice. If you are happy with the image the scratch container can be deleted.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Quite some time ago I blogged about how you could build your customzized PostgreSQL container by using a Dockerfile and Docker build. In the meantime Red Hat replaced Docker in OpenShift and SUSE replaced Docker as well in CaaS. As a consequence there need to be other ways of building containers and one of them [&hellip;]<\/p>\n","protected":false},"author":29,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229],"tags":[1713,762,1646,77],"type_dbi":[],"class_list":["post-12873","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","tag-buildah","tag-containers","tag-podman","tag-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Creating a customized PostgreSQL container using buildah - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating a customized PostgreSQL container using buildah\" \/>\n<meta property=\"og:description\" content=\"Quite some time ago I blogged about how you could build your customzized PostgreSQL container by using a Dockerfile and Docker build. In the meantime Red Hat replaced Docker in OpenShift and SUSE replaced Docker as well in CaaS. As a consequence there need to be other ways of building containers and one of them [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-10-16T12:09:07+00:00\" \/>\n<meta name=\"author\" content=\"Daniel Westermann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@westermanndanie\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Westermann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\"},\"author\":{\"name\":\"Daniel Westermann\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"headline\":\"Creating a customized PostgreSQL container using buildah\",\"datePublished\":\"2019-10-16T12:09:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\"},\"wordCount\":486,\"commentCount\":0,\"keywords\":[\"buildah\",\"Containers\",\"podman\",\"PostgreSQL\"],\"articleSection\":[\"Database Administration &amp; Monitoring\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\",\"name\":\"Creating a customized PostgreSQL container using buildah - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2019-10-16T12:09:07+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creating a customized PostgreSQL container using buildah\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\",\"name\":\"Daniel Westermann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"caption\":\"Daniel Westermann\"},\"description\":\"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.\",\"sameAs\":[\"https:\/\/x.com\/westermanndanie\"],\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Creating a customized PostgreSQL container using buildah - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/","og_locale":"en_US","og_type":"article","og_title":"Creating a customized PostgreSQL container using buildah","og_description":"Quite some time ago I blogged about how you could build your customzized PostgreSQL container by using a Dockerfile and Docker build. In the meantime Red Hat replaced Docker in OpenShift and SUSE replaced Docker as well in CaaS. As a consequence there need to be other ways of building containers and one of them [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/","og_site_name":"dbi Blog","article_published_time":"2019-10-16T12:09:07+00:00","author":"Daniel Westermann","twitter_card":"summary_large_image","twitter_creator":"@westermanndanie","twitter_misc":{"Written by":"Daniel Westermann","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/"},"author":{"name":"Daniel Westermann","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"headline":"Creating a customized PostgreSQL container using buildah","datePublished":"2019-10-16T12:09:07+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/"},"wordCount":486,"commentCount":0,"keywords":["buildah","Containers","podman","PostgreSQL"],"articleSection":["Database Administration &amp; Monitoring"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/","url":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/","name":"Creating a customized PostgreSQL container using buildah - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2019-10-16T12:09:07+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/creating-a-customized-postgresql-container-using-buildah\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Creating a customized PostgreSQL container using buildah"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66","name":"Daniel Westermann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","caption":"Daniel Westermann"},"description":"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.","sameAs":["https:\/\/x.com\/westermanndanie"],"url":"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=12873"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12873\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=12873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=12873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=12873"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=12873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}