{"id":406418,"date":"2022-02-16T17:00:04","date_gmt":"2022-02-16T14:00:04","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/"},"modified":"2022-02-16T17:00:04","modified_gmt":"2022-02-16T14:00:04","slug":"how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/","title":{"rendered":"#How to Deploy PostgreSQL as a Docker Container \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a3056b9c8454\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a3056b9c8454\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Getting_Started\" >Getting Started<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Supplying_the_Password_as_a_File\" >Supplying the Password as a File<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Connecting_to_Your_Database\" >Connecting to Your Database<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Connecting_From_Other_Docker_Containers\" >Connecting From Other Docker Containers<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Configuring_PostgreSQL\" >Configuring PostgreSQL<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Seeding_the_Database\" >Seeding the Database<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Creating_a_Custom_Database_Image\" >Creating a Custom Database Image<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Should_You_Containerize_Your_Production_Database\" >Should You Containerize Your Production Database?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-postgresql-as-a-docker-container-cloudsavvy-it\/#Summary\" >Summary<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How to Deploy PostgreSQL as a Docker Container \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage aligncenter size-full wp-image-15436\" data-pagespeed-lazy-srcset=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/01\/3a8a0535.jpg?width=398&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 400w, https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/01\/3a8a0535.jpg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 1200w\" sizes=\"auto, 400w, 1200w\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/01\/3a8a0535.jpg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Illustration showing the Docker and Postgres logos\" width=\"1202\" height=\"677\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>PostgreSQL, also referred to as Postgres, is the leading object-relational database system. It\u2019s popular because of its high level of compliance with the SQL standard and inclusion of additional features that simplify working with complex datasets at scale.<\/p>\n<p>PostgreSQL uses a traditional client-server architecture so you need to run it independently of your <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>lication\u2019s code. In this guide, you\u2019ll deploy a PostgreSQL server instance as a Docker container. This avoids adding packages to your host machine and helps to isolate your database from the other parts of your stack. Make sure you\u2019ve got Docker installed before you continue.<\/p>\n<h2 id=\"getting-started\"><span class=\"ez-toc-section\" id=\"Getting_Started\"><\/span>Getting Started<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>PostgreSQL has an <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/hub.docker.com\/_\/postgres\">official image<\/a> on Docker Hub which is available in several different variants. Tags let you select between major PostgreSQL versions from v9 to v14 and choose the operating system used as the base image. Alpine, Debian Stretch, and Debian Bullseye are offered.<\/p>\n<p>For the purposes of this tutorial, we\u2019ll use the <code>postgres:14<\/code> tag which provides PostgreSQL 14 atop Bullseye. You\u2019re free to select a different version to suit your requirements.<\/p>\n<p>Start a PostgreSQL container using the <code>docker run<\/code> command:<\/p>\n<pre>docker run -d \\&#13;\n    --name postgres \\&#13;\n    -p 5432:5432&#13;\n    -e POSTGRES_PASSWORD=&lt;password&gt; \\&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    postgres:14<\/pre>\n<p>You <strong>must<\/strong> supply a value for the <code>POSTGRES_PASSWORD<\/code> environment variable. This defines the password which will be assigned to Postgres\u2019 default superuser account. The username defaults to <code>postgres<\/code> but can be changed by setting the <code>POSTGRES_USER<\/code> environment variable.<\/p>\n<p>The <code>-v<\/code> flag is used to mount a Docker volume to the PostgreSQL container\u2019s data directory. A named volume called <code>postgres<\/code> is referenced; Docker will either create it or reattach the volume if it already exists. You should use a volume to store your database outside the container. Without one you\u2019ll use your data when the container stops.<\/p>\n<p>PostgreSQL listens on port 5432 by default. The container port is bound to port 5432 on your Docker host by the <code>-p<\/code> flag. The <code>-d<\/code> flag is used to start the container in detached mode, effectively making it a background service that keeps running until stopped with <code>docker stop<\/code>.<\/p>\n<h3 id=\"supplying-the-password-as-a-file\"><span class=\"ez-toc-section\" id=\"Supplying_the_Password_as_a_File\"><\/span>Supplying the Password as a File<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If you\u2019re uncomfortable about supplying your superuser password as a plain-text CLI flag, you can inject it as a file via a volume instead. You should then set the <code>POSTGRES_PASSWORD_FILE<\/code> environment variable to give Postgres the path to that file:<\/p>\n<pre>docker run -d \\&#13;\n    --name postgres \\&#13;\n    -p 5432:5432&#13;\n    -e POSTGRES_PASSWORD_FILE=\/run\/secrets\/postgres-password \\&#13;\n    -v .\/postgres-password.txt:\/run\/secrets\/postgres-password&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    postgres:14<\/pre>\n<p>This technique also works for <code>POSTGRES_USER<\/code> and <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/hub.docker.com\/_\/postgres#environment-variables\">other supported environment variables<\/a>.<\/p>\n<h2 id=\"connecting-to-your-database\"><span class=\"ez-toc-section\" id=\"Connecting_to_Your_Database\"><\/span>Connecting to Your Database<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>As PostgreSQL was bound to port 5432 above, you could connect to your database on <code>localhost:5432<\/code> from any compatible client. Use the credentials you assigned as environment variables when starting the container.<\/p>\n<p>The Docker image also includes the <code>psql<\/code> binary which you can invoke with <code>docker exec<\/code>. Use this to quickly interact with your database from a PostgreSQL shell within the container.<\/p>\n<pre>docker exec -it postgres psql -U postgres<\/pre>\n<h3 id=\"connecting-from-other-docker-containers\"><span class=\"ez-toc-section\" id=\"Connecting_From_Other_Docker_Containers\"><\/span>Connecting From Other Docker Containers<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Creating a Docker network is the preferred way to access PostgreSQL from other containers on the same host. This avoids binding the Postgres server\u2019s port and potentially exposing the service to your host\u2019s wider network.<\/p>\n<p>Create a Docker network:<\/p>\n<pre>docker network create my-app<\/pre>\n<p>Start your Postgres container with a connection to the network by using the <code>--network<\/code> flag with <code>docker run<\/code>:<\/p>\n<pre>docker run -d \\&#13;\n    --name postgres \\&#13;\n    --network my-app \\&#13;\n    -e POSTGRES_PASSWORD=&lt;password&gt; \\&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    postgres:14<\/pre>\n<p>Now join your application container to the same network:<\/p>\n<pre>docker run -d&#13;\n    --name api&#13;\n    --network my-app&#13;\n    my-api:latest<\/pre>\n<p>The containers in the network can reach Postgres using the <code>postgres<\/code> hostname, as this is the <code>name<\/code> assigned to the Postgres container. Use port 5432 to complete the connection.<\/p>\n<h2 id=\"configuring-postgresql\"><span class=\"ez-toc-section\" id=\"Configuring_PostgreSQL\"><\/span>Configuring PostgreSQL<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You can pass PostgreSQL server options using <code>-c<\/code> flags after the image name in your <code>docker run<\/code> command:<\/p>\n<pre>docker run -d \\&#13;\n    --name postgres \\&#13;\n    -p 5432:5432&#13;\n    -e POSTGRES_PASSWORD=&lt;password&gt; \\&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    postgres:14 -c max_connections=100<\/pre>\n<p>Everything after the image name gets passed to the command started in the container. This command will be the PostgreSQL server binary in the case of the Postgres image.<\/p>\n<p>You can use a custom config file when you\u2019re setting the values of several options. You\u2019ll need to use another Docker volume to mount your file into the container, then supply one <code>-c<\/code> flag to instruct Postgres where to look:<\/p>\n<pre>docker run -d \\&#13;\n    --name postgres \\&#13;\n    -p 5432:5432&#13;\n    -e POSTGRES_PASSWORD=&lt;password&gt; \\&#13;\n    -v .\/postgres.conf:\/etc\/postgresql\/postgresql.conf \\&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    postgres:14 -c config_file=\/etc\/postgresql\/postgresql.conf<\/pre>\n<p>This example uses a Docker bind mount to get the <code>postgres.conf<\/code> file in your working directory mounted into the container\u2019s <code>\/etc\/postgresql<\/code> directory. For a reference of the options you can set with binary flags or config file directives, refer to the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/config-setting.html\">PostgreSQL documentation<\/a>.<\/p>\n<h2 id=\"seeding-the-database\"><span class=\"ez-toc-section\" id=\"Seeding_the_Database\"><\/span>Seeding the Database<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Docker image supports seed files placed into the <code>\/docker-entrypoint-initdb.d<\/code> directory. Any <code>.sql<\/code> or <code>.sql.gz<\/code> files will be executed to initialize the database. This occurs after the default user account and <code>postgres<\/code> database have been created. You can also add <code>.sh<\/code> files to run arbitrary shell scripts. All scripts are executed in alphabetical order.<\/p>\n<p>This mechanism means all you need to seed your database is a set of SQL or shell scripts named in the correct sequential order. Mount these into your new container using a <code>-v<\/code> flag with <code>docker run<\/code>:<\/p>\n<pre>docker run -d \\&#13;\n    --name postgres \\&#13;\n    -p 5432:5432&#13;\n    -e POSTGRES_PASSWORD=&lt;password&gt; \\&#13;\n    -v .\/db-seed-files\/:\/etc\/docker-entrypoint-initdb.d \\&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    postgres:14<\/pre>\n<p>The initialization scripts will only be used when the Postgres data directory is empty. For practical purposes, that means they\u2019ll run the first time the container starts with a new empty volume attached.<\/p>\n<h2 id=\"creating-a-custom-database-image\"><span class=\"ez-toc-section\" id=\"Creating_a_Custom_Database_Image\"><\/span>Creating a Custom Database Image<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You could choose to encapsulate your config file and initialization scripts in your own Docker image. This would let anyone with access to the image spin up a new PostgreSQL instance that\u2019s preconfigured for your application. Here\u2019s a simple Dockerfile which you could use:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"dockerfile\">\n<pre class=\"de1\">FROM postgres:14&#13;\nCOPY postgres.conf \/etc\/postgresql\/postgresql.conf&#13;\nCOPY db-seed-files\/ \/etc\/docker-entrypoint-initdb.d\/&#13;\nCMD [\"-c\", \"config_file=\/etc\/postgresql\/postgresql.conf\"]<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Build your custom image:<\/p>\n<pre>docker build -t custom-postgres:latest .<\/pre>\n<p>The build instructions in the Dockerfile will copy the PostgreSQL config file and initialization scripts from your working directory and embed them into the container image. Now you can start a database container without manually supplying the resources:<\/p>\n<pre>docker run -d \\&#13;\n    --name custom-postgres \\&#13;\n    -p 5432:5432&#13;\n    -e POSTGRES_PASSWORD=&lt;password&gt; \\&#13;\n    -v postgres:\/var\/lib\/postgresql\/data \\&#13;\n    custom-postgres:latest<\/pre>\n<h2 id=\"should-you-containerize-your-production-database\"><span class=\"ez-toc-section\" id=\"Should_You_Containerize_Your_Production_Database\"><\/span>Should You Containerize Your Production Database?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>It can be difficult to decide whether to run a database in Docker. Containerizing PostgreSQL makes for an easier set up experience but is sometimes more challenging to maintain. You need to take care when managing your container to avoid data loss in the future. Docker also adds a modest performance overhead which is worth considering when you anticipate tour database will be working with very large data volumes.<\/p>\n<p>Docker\u2019s benefits are increased portability, ease of scaling, and developer efficiency. Containerizing your database lets anyone spin up a fresh instance using Docker, without manually installing and configuring PostgreSQL first. Writing a Dockerfile for your PostgreSQL database that adds your config file and SQL seed scripts is therefore a good way to help developers rapidly start new environments.<\/p>\n<h2 id=\"summary\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>PostgreSQL is an advanced SQL-based database engine that adds object-relational capabilities. While you may choose to run a traditional deployment in production, using a containerized instance simplifies set up and helps developers quickly spin up their own infrastructure.<\/p>\n<p>The most critical aspect of a Dockerized deployment is to ensure you\u2019re using a volume to store your data. This will allow you to stop, replace, and update your container to a later image version without losing your database. Beyond storage you should assess how you\u2019re going to connect to Postgres and avoid binding ports to your host unless necessary. When connecting from another container, it\u2019s best to use a shared Docker network to facilitate access.\n<\/p><\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/15435\/how-to-deploy-postgresql-as-a-docker-container\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How to Deploy PostgreSQL as a Docker Container \u2013 CloudSavvy IT&#8221; PostgreSQL, also referred to as Postgres, is the leading object-relational database system. It\u2019s popular because of its high level of compliance with the SQL standard and inclusion of additional features that simplify working with complex datasets at scale. PostgreSQL uses a traditional client-server architecture&#8230;<\/p>\n","protected":false},"author":1,"featured_media":406419,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/01\/3a8a0535.jpg","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-406418","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/406418","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=406418"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/406418\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/406419"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=406418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=406418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=406418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}