{"id":112214,"date":"2026-09-23T12:00:00","date_gmt":"2026-09-23T12:00:00","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=112214"},"modified":"2026-09-08T15:55:21","modified_gmt":"2026-09-08T15:55:21","slug":"how-to-run-postgresql-in-docker-getting-started-with-postgresql-part-one","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/postgresql\/how-to-run-postgresql-in-docker-getting-started-with-postgresql-part-one\/","title":{"rendered":"How to run PostgreSQL in Docker (getting started with PostgreSQL, part one)"},"content":{"rendered":"\n<p><strong>The goal of this guide is simple: get <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/postgresql\/\" target=\"_blank\" rel=\"noreferrer noopener\">PostgreSQL<\/a> up and running in the fastest, easiest way. You&#8217;ll then learn how to create databases in PostgreSQL and the objects that live within them.<\/strong><\/p>\n\n\n\n<p><strong>The two easiest ways to get started working in PostgreSQL are to either use <a href=\"https:\/\/www.red-gate.com\/simple-talk\/devops\/containers-and-virtualization\/a-quick-guide-on-how-to-containerize-your-application-using-docker\/\" target=\"_blank\" rel=\"noreferrer noopener\">containers<\/a>, or create an account with a <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/migrating-from-on-prem-to-the-cloud-dba-stories\/\" target=\"_blank\" rel=\"noreferrer noopener\">cloud<\/a> provider. In this case, we&#8217;ll be using containers.<\/strong><\/p>\n\n\n\n<div id=\"callout-block_3180bb71054fd13bd5f86c1c2298e49a\" class=\"callout alignnone\">\n    <div class=\"child-last:mb-0 child-first:mt-0 bg-gray-50 dark:bg-gray-950 p-4xl my-3xl\">\n\n<p><strong>Important note before you continue&#8230;<\/strong><\/p>\n\n\n\n<p>This is the first part in Grant Fritchey&#8217;s complete set of step-by-step walkthroughs (guides) for getting started with PostgreSQL, designed for any IT professional or hobbyist who wants to add PostgreSQL to their existing skillset.  <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/how-to-get-started-with-postgresql-a-complete-set-of-hands-on-classes\/\" target=\"_blank\" rel=\"noreferrer noopener\">Click here for the full series<\/a>.<\/p>\n\n\n\n<p>Originally intended to be proctored classes given in a live, in-person environment, Grant has aimed to make the documentation and scripts clear enough to walk through them independently from home.<\/p>\n\n\n\n<p>Before getting started, please check that you have <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/how-to-get-started-with-postgresql-a-complete-set-of-hands-on-classes\/#:~:text=What%20do%20I%20need%20to%20follow%20this%20walkthrough%3F\" target=\"_blank\" rel=\"noreferrer noopener\">everything you need.<\/a><\/p>\n\n<\/div>\n<\/div> \n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-retrieve-docker-images-using-pull\">How to retrieve Docker images using Pull<\/h2>\n\n\n\n<p><strong>The goal of this walkthrough is, of course, to have a running PostgreSQL container. However, before a container can be created, the necessary image for that container must be retrieved.<\/strong><\/p>\n\n\n\n<p>It&#8217;s possible to simply issue a\u00a0<code>docker run<\/code>\u00a0command and, if no image is found, it&#8217;ll automatically attempt to first\u00a0<code>pull<\/code>\u00a0that image. While this is fine, it&#8217;s actually better to issue the <code>pull<\/code> command separately.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-why-use-docker-pull\">Why use Docker Pull?<\/h3>\n\n\n\n<p>For a start, a <code>run<\/code>&nbsp;command will only run a local version of the image &#8211; not necessarily the latest one. Second, a <code>pull<\/code>&nbsp;command validates the image <em>before<\/em> execution, ensuring that malformed or malicious containers are <em>not<\/em> run. And finally, retrieving the image first makes it possible to work fully offline &#8211; a nice benefit in itself.<\/p>\n\n\n\n<p>For all these reasons, we&#8217;ll use&nbsp;<code>pull<\/code>&nbsp;as the foundation for building out PostgreSQL containers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-how-to-use-docker-pull\">How to use Docker Pull<\/h3>\n\n\n\n<p>There are many possible <a href=\"https:\/\/www.docker.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker<\/a> images, but we&#8217;ll start with the most generic PostgreSQL one for now. Before getting started, make sure you&#8217;re connected to the internet, and that your Docker service is running. Then, run the <code>docker pull postgres:latest<\/code> command.<\/p>\n\n\n\n<p>It&#8217;s worth noting that the <code>:latest<\/code> part of the command isn&#8217;t actually necessary. By default, a\u00a0<code>pull<\/code>\u00a0command, if given no other instruction, will get the latest, stable, image. <\/p>\n\n\n\n<p>Also, depending on the service you&#8217;re running, you substitute\u00a0<code>podman<\/code>\u00a0or\u00a0<code>nerdctl<\/code>\u00a0for the\u00a0<code>docker<\/code>\u00a0command. All other aspects of the command will stay the same.<\/p>\n\n\n\n<p><em>And, to reiterate, the&nbsp;<code>latest<\/code>&nbsp;image will not be the most cutting edge version under development. Rather, it&#8217;s just the newest stable release.<\/em><\/p>\n\n\n\n<p>This command <em>could<\/em> take a while depending on the speed and bandwidth of your internet connection &#8211; the progress of which you&#8217;ll be able to see in your command line interface. When it&#8217;s done, you&#8217;re ready to validate the image.<\/p>\n\n\n\n<p>To validate that the Docker image was downloaded successfully, you can run the <code>docker images<\/code> command.<\/p>\n\n\n\n<p>On a brand new machine, you&#8217;ll probably only see a <code>REPOSITORY<\/code> (with one or two images), <code>postgres<\/code>, and possibly <code>hello-world<\/code>. <\/p>\n\n\n\n<p>Also pay attention to the TAG column. Your <code>postgres<\/code> image should show a tag of &#8216;latest&#8217;. If that&#8217;s the case, you&#8217;re ready to create a container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-how-to-pull-a-specific-image-with-docker-pull\">How to pull a specific image with Docker Pull<\/h3>\n\n\n\n<p><a href=\"https:\/\/github.com\/ScaryDBA\/GettingStartedWithPostgreSQL\/blob\/main\/01.%20Docker%20Pull\/dockerpull.md#pulling-a-specific-image\"><\/a>If you wanted to have a specific version of PostgreSQL, it&#8217;s possible by supplying the documented tag of that version. For a complete listing, the PostgreSQL community maintains the Docker PostgreSQL image on the <a href=\"https:\/\/hub.docker.com\/_\/postgres\" target=\"_blank\" rel=\"noreferrer noopener\">Docker hub here.<\/a><\/p>\n\n\n\n<p>To pull a particular version, you just need to supply it. For example, to pull version 17.10, you&#8217;d run <br><code>docker pull postgres:17.10<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-create-a-container-using-docker-run\">How to create a container using Docker Run<\/h2>\n\n\n\n<p>Once an image has been created locally, you can now use that image to create containers. As stated previously, you can simply use\u00a0<code>docker run<\/code>\u00a0to both pull the image and create the container. <\/p>\n\n\n\n<p>We&#8217;ll also need to break down the core requirements for creating a PostgreSQL container using\u00a0<code>docker run<\/code>. Here&#8217;s the full command we&#8217;ll be using:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">docker run -d --name StartingPostgreSQL \\\n    -p 5432:5432 \\\n    -e POSTGRES_PASSWORD=Some*Passw0rd \\\n    -v \/mnt\/c\/Users\/grant\/bu:\/var\/lib\/postgresql\/bu \\\n    -e POSTGRES_USER=postgres \\\n    postgres:latest<\/pre><\/div>\n\n\n\n<p>Before we run the script, though, let&#8217;s talk about a few important pieces of information here.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-how-to-create-a-volume-on-your-container-and-why-you-should\">How to create a volume on your container (and why you should)<\/h3>\n\n\n\n<p>First, I&#8217;m going to recommend you create at least one <a href=\"https:\/\/www.red-gate.com\/simple-talk\/devops\/containers-and-virtualization\/working-windows-containers-docker-save-data\/\" target=\"_blank\" rel=\"noreferrer noopener\">volume on your container<\/a> (the\u00a0<code>-v<\/code>\u00a0flag.) A volume is way to map an external directory on your machine to a location within the container. <\/p>\n\n\n\n<p>Then, you can place files into that folder and they&#8217;ll be readable within the container <em>and<\/em> outside, in your operating system. If you wanted to have&nbsp;<code>*.sql<\/code>&nbsp;files or PostgreSQL dump files available within the container, this is the easy way to do it.<\/p>\n\n\n\n<p>Because of this, you&#8217;ll need to ensure that you have that folder already created on your local machine. The example script above is for a <a href=\"https:\/\/rancherdesktop.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Rancher Desktop<\/a> path. You&#8217;d need a different path for Windows or Linux unless you&#8217;re running everything through <a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/wsl\/\" target=\"_blank\" rel=\"noreferrer noopener\">WSL<\/a> on Windows.<\/p>\n\n\n\n<p>You can get very sophisticated with volumes if you choose but, for our purposes, just the ability to easily move scripts into the container is enough.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-naming-your-container\">Naming your container<\/h3>\n\n\n\n<p>You don&#8217;t have to supply a name to the container, but it does make managing it easier. This is the&nbsp;<code>--name<\/code>&nbsp;flag.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-port-mapping\">Port mapping<\/h3>\n\n\n\n<p><a href=\"https:\/\/github.com\/ScaryDBA\/GettingStartedWithPostgreSQL\/blob\/main\/02.%20Docker%20Run\/dockerrun.md#port-mapping\"><\/a>Next, you have to map between an external and internal port. Since I&#8217;m only running one container, I&#8217;ll map it to the default PostgreSQL port, 5432 (<code>-p 5432:5432<\/code>). If you want to run more than one container hosting PostgreSQL, you&#8217;ll need to provide a different external port value (the first number.)<\/p>\n\n\n\n<p>For example, if you already have PostgreSQL running within a container (or locally), you might substitute<br><code>-p 5433:5432<\/code>\u00a0to map to a different port. You&#8217;ll then need to provide that <em>non-default<\/em> port value to any connection to that PostgreSQL cluster.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-environment-variable-flags\">Environment variable flags<\/h3>\n\n\n\n<p><a href=\"https:\/\/github.com\/ScaryDBA\/GettingStartedWithPostgreSQL\/blob\/main\/02.%20Docker%20Run\/dockerrun.md#environment-variable-flags\"><\/a>For a container, a simple role is all that&#8217;s needed to connect to the cluster running inside the container. I have to use the environment variable flag,\u00a0<code>-e<\/code> to map to a particular key two times:\u00a0<br><code>POSTGRES_PASSWORD<\/code>\u00a0and\u00a0<code>POSTGRES_USER<\/code>.<\/p>\n\n\n\n<p>The name supplied to\u00a0<code>POSTGRES_USER<\/code>\u00a0is going to be the default super user (system administrator) of the PostgreSQL <a href=\"https:\/\/www.red-gate.com\/simple-talk\/other\/creating-an-azure-postgresql-cluster-and-connecting-to-it\/\" target=\"_blank\" rel=\"noreferrer noopener\">cluster<\/a> running in the container. In the example, I use the default value for the super user in most PostgreSQL installs: <code>postgres<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-image\">Image<\/h3>\n\n\n\n<p>Finally, I supply the name of the Docker image:&nbsp;<code>postgres:latest.<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-how-to-execute-the-script\">How to execute the script <\/h3>\n\n\n\n<p>When you execute the command, you receive back an identifier for the container you created. You can either use this identifier <em>or<\/em> the name of the container you created. I recommend the latter, simply because it&#8217;s easier.<\/p>\n\n\n\n<p>To validate that the container was successfully created, run this command:<br><code>docker ps -f 'name=StartingPostgreSQL'<\/code><\/p>\n\n\n\n<p>This should result in something similar to the following:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                                         NAMES\n6ae8a06273fe   postgres:latest   \"docker-entrypoint.s\u2026\"   6 seconds ago   Up 5 seconds   0.0.0.0:5432-&gt;5432\/tcp, [::]:5432-&gt;5432\/tcp   StartingPostgreSQL<\/pre><\/div>\n\n\n\n<p>As you can see from the output, you get the ID for the container itself, as well as the name, the image used in creation, when it was created, and the current status along with any ports. And that&#8217;s it! You now have a functional PostgreSQL cluster running within a container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-how-to-stop-start-the-container\">How to stop\/start the container<\/h3>\n\n\n\n<p>You can stop the container by issuing the <code>docker stop StartingPostgreSQL<\/code> command. Then, to restart the container, issue the <code>docker start StartingPostgreSQL<\/code> command. If you wish to continue following this guide, I advise leaving the container in a running state.<\/p>\n\n\n\n<section id=\"my-first-block-block_de4f5c3bb8a9659a03445ca42980908a\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Get started with PostgreSQL &#8211; free book download<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            &#8216;Introduction to PostgreSQL for the data professional&#8217;, written by Grant Fritchey and Ryan Booz, covers all the basics of how to get started with PostgreSQL.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/hub\/books\/introduction-to-postgresql-for-the-data-professional\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Download your free copy: Get started with PostgreSQL - free book download\">Download your free copy<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-gain-access-to-the-container-operating-system-os\">How to gain access to the container operating system (OS)<\/h2>\n\n\n\n<p>While running PostgreSQL within a container, certain operations have to be completed with the <em>minimal<\/em> Linux OS that supports PostgreSQL in its execution within the container. In this part of the guide, we&#8217;ll be connecting to PostgreSQL using <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/postgresql\/postgresql-basics-getting-started-with-psql\/\" target=\"_blank\" rel=\"noreferrer noopener\"><code>psql<\/code><\/a> &#8211; the default command line utility for running <a href=\"https:\/\/www.red-gate.com\/simple-talk\/other\/what-is-sql\/\" target=\"_blank\" rel=\"noreferrer noopener\">SQL<\/a> within PostgreSQL.<\/p>\n\n\n\n<p>In other parts of the guide, we may need to change PostgreSQL configuration files or perform other actions within the Linux OS. Therefore, we&#8217;ll do a quick overview of how to connect to that OS within the container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-the-docker-exec-command\">The Docker <code>exec<\/code> command<\/h3>\n\n\n\n<p>The <code>exec<\/code> command in Docker is used at the command line to open a shell into the running container. From there, you can perform actions directly within the container. <\/p>\n\n\n\n<p>In our case, we&#8217;ll be using <code>psql<\/code> to run SQL queries. The command to start a shell within a container is simple: <code>docker exec -it StartingPostgreSQL \"bash\"<\/code><\/p>\n\n\n\n<p>The <code>-it<\/code> flag tells Docker that we&#8217;re starting an interactive shell command. We have to supply the container to which we want to connect through the container name. Finally, we supply what we wish to execute: a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bash_(Unix_shell)\" target=\"_blank\" rel=\"noreferrer noopener\">Bash<\/a> shell.<\/p>\n\n\n\n<p>Running this from the command line, you&#8217;ll see your folder change from whatever it was to something like this:<br><code>root@6ae8a06273fe:\/#<\/code><\/p>\n\n\n\n<p>This shows that I&#8217;m at the root of the container within Bash. Do note that the numbered value is supplied by Docker so will likely be different on your container.<\/p>\n\n\n\n<p>You can validate that you&#8217;re not local by running some simple commands. For example, the <code>ls<\/code> command will show you the folder and file listing within the container. These will undoubtedly be different than your machine.<\/p>\n\n\n\n<p>A more effective check would be to look for the docker environment values using the <code>ls -l \/.dockerenv<\/code> command. The output should be something similar to this:<br><code>-rwxr-xr-x 1 root root 0 Jun 18 13:26 \/.dockerenv<\/code> (and of course, the date will be different in your output).<\/p>\n\n\n\n<p>Another way to validate that you&#8217;re running in the PostgreSQL container (assuming you&#8217;re not running PostgreSQL locally as a service) would be to look for the <code>$POSTGRES_USER<\/code> value using <br><code>echo $POSTGRES_USER<\/code>. <\/p>\n\n\n\n<p>If this returns <code>postgres<\/code> <em>and<\/em> you&#8217;ve followed the scripts as written, then you&#8217;re absolutely within a shell in your container.<\/p>\n\n\n\n<p>To leave the shell, simply issue the <code>exit<\/code> command &#8211; dropping you out of the shell within your container and back to the command line. You can leave the shell open for the next part of the guide.<\/p>\n\n\n\n<div id=\"callout-block_3180bb71054fd13bd5f86c1c2298e49a\" class=\"callout alignnone\">\n    <div class=\"child-last:mb-0 child-first:mt-0 bg-gray-50 dark:bg-gray-950 p-4xl my-3xl\">\n\n<p><strong>Important note<\/strong><\/p>\n\n\n\n<p>While the <em>standard<\/em> PostgreSQL container does have a Bash shell, some others may not. You can simply run &#8216;sh&#8217; as the shell to get access to a bare bones shell on most containers.<\/p>\n\n<\/div>\n<\/div> \n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-connect-to-postgresql\">How to connect to PostgreSQL<\/h2>\n\n\n\n<p><strong>Now, let&#8217;s focus on how to connect to PostgreSQL for the first time. Here&#8217;s everything you need to know in this step-by-step walkthrough\/guide.<\/strong><\/p>\n\n\n\n<p>Before we continue on to executing <code>psql<\/code>, it&#8217;s worth double checking that we&#8217;re actually connected to the shell in our container. To check this, run the <code>docker exec -it StartingPostgreSQL \"bash\"<\/code> command.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-what-is-psql-in-postgresql\">What is <code>psql<\/code> in PostgreSQL?<\/h3>\n\n\n\n<p><code>psql<\/code> is considered to be the official interface for PostgreSQL. It&#8217;s a command line for interacting with, and administering, PostgreSQL <a href=\"https:\/\/www.red-gate.com\/simple-talk\/other\/creating-an-azure-postgresql-cluster-and-connecting-to-it\/\" target=\"_blank\" rel=\"noreferrer noopener\">clusters<\/a>. You can issue SQL commands as well as taking advantage of the utilities built into <code>psql<\/code>. <\/p>\n\n\n\n<p>In this part of the guide, we&#8217;ll explore the basic connection to PostgreSQL using <code>psql<\/code>. We&#8217;ll then use <code>psql<\/code> to create objects within the cluster. If you&#8217;ve been following from the start, you&#8217;ll be running this within a Bash shell inside your container. However, you wouldn&#8217;t run it any differently from the command line of your host OS. <\/p>\n\n\n\n<p>For our container as configured, we connect to it through <code>psql<\/code> with the <code>psql -d postgres -h localhost -U postgres<\/code> command. When run inside a container, you won&#8217;t be prompted for a password; you&#8217;re in a trusted environment. <\/p>\n\n\n\n<p>Otherwise, when running <code>psql<\/code>, you&#8217;ll need to supply the password used when creating the container (in the example, Some*Passw0rd). You&#8217;re forced to provide a password in order to keep the password out of the history of commands in your <a href=\"https:\/\/en.wikipedia.org\/wiki\/Command-line_interface\" target=\"_blank\" rel=\"noreferrer noopener\">CLI (command line interface)<\/a> as a beneficial security measure. <\/p>\n\n\n\n<p>Meanwhile, if you&#8217;re running <code>psql<\/code> from an external command line &#8211; not the Bash shell as we&#8217;re doing &#8211; there are a couple of ways to supply a password without typing it each time. One way is to create an environment variable on your machine, but that&#8217;s less secure than simply entering the password. <\/p>\n\n\n\n<p>Another way is to create a secured file (chmod 0600) in your file system. We&#8217;ll just stick to the password for our examples.<\/p>\n\n\n\n<p>We&#8217;re logging in to the default database,&nbsp;<code>postgres<\/code>, and using the user we created earlier in the guide (<code>postgres<\/code>).<\/p>\n\n\n\n<p>Your prompt should now change to something like this:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">psql (18.4 (Debian 18.4-1.pgdg13+1))\nType \"help\" for help.\n\npostgres=# \n<\/pre><\/div>\n\n\n\n<p>We can validate that we&#8217;re successfully connected to PostgreSQL several ways. First, we can use one of the meta commands (so designated by a backslash&nbsp;<code>\\<\/code>&nbsp;before the command). All meta commands are stored in&nbsp;<code>*.sql<\/code>&nbsp;files since they can only be run through <code>psql<\/code>. <\/p>\n\n\n\n<p>To see the connection information of PostgreSQL, we can run the <code>\\conninfo<\/code> command, which will return a bunch of information about your connection:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">      Connection Information\n      Parameter       |   Value   \n----------------------+-----------\n Database             | postgres\n Client User          | postgres\n Host                 | localhost\n Host Address         | ::1\n Server Port          | 5432\n Options              | \n Protocol Version     | 3.0\n Password Used        | false\n GSSAPI Authenticated | false\n Backend PID          | 87\n SSL Connection       | false\n Superuser            | on\n Hot Standby          | off\n(13 rows)<\/pre><\/div>\n\n\n\n<p>Do note that, if your CLI window has fewer than 13 lines available, it will &#8216;page&#8217; the results by default. You&#8217;ll need to use&nbsp;<code>q<\/code>&nbsp;to move to the next page.<\/p>\n\n\n\n<p>Since we&#8217;re connected to <code>psql<\/code>, you can immediately run a query instead of a meta command. One thing to know up front, every connection to PostgreSQL is to a specific database and that database only &#8211; there&#8217;s no concept of <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/database-administration-sql-server\/running-queries-across-many-sql-server-databases\/\" target=\"_blank\" rel=\"noreferrer noopener\">cross-database queries<\/a>. Any query we issue is going to run against the database specified in the connection. <\/p>\n\n\n\n<p>In this case, it&#8217;ll be the <code>postgres<\/code> database. For clarity, we can use the <code>SELECT version();<\/code> query to understand exactly <em>where<\/em> we&#8217;re connected at any given time.<\/p>\n\n\n\n<p>At the time of writing this guide, the output is:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">                                                     version                                                       \n--------------------------------------------------------------------------------------------------------------------\n PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit`\n\nA few things to note. First, in the query you'll see the end terminated with a semi-colon (;). In PostgreSQL, query statements must be terminated with a semi-colon. This is not like some data platforms where the statement terminator of a semi-colon is syntactic sugar. It's required for PostgreSQL. However, it's not required for the meta commands. Second, you get to see exactly how this container was created. Not simply that it's PostgreSQL. It's version 18.4. The next is not that it's Linux. It's Debian 14.2.0. You're supplied full information about this Postgres cluster. You'll also note the \"-1.pgdg13+1\" in the parenthesis. This is the version of the container and who compiled it. \n\nWhile we're here, let's try out a couple of more meta commands that are useful to know. First, and probably most important, you can get a full listing of all meta commands:\n\n`\\?<\/pre><\/div>\n\n\n\n<p>It&#8217;ll likely enter into paging. <\/p>\n\n\n\n<p><em>We can also get a list of databases using the <code>\\l<\/code> command, but this is unlikely to page on our example container because there should only be three databases: <code>postgres<\/code> (the one we&#8217;re connected to), <code>template0<\/code>, and <code>template1<\/code>. We&#8217;ll discuss templates more later in the series.<\/em><\/p>\n\n\n\n<p>To leave a <code>psql<\/code> session such as this, use the meta command\u00a0<code>\\q<\/code>. And that&#8217;s it: you now have the basics of <code>psql<\/code> under your belt! In part two, we will start actually working <em>within<\/em> PostgreSQL.<\/p>\n\n\n\n<section id=\"my-first-block-block_98d9c36c4d4382da0ff47389eeb8e221\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Simple Talk is brought to you by Redgate Software<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            Take control of your databases with the trusted Database DevOps solutions provider. Automate with confidence, scale securely, and unlock growth through AI.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/solutions\/overview\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Discover how Redgate can help you: Simple Talk is brought to you by Redgate Software\">Discover how Redgate can help you<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. How do I run PostgreSQL in a Docker container?<\/h3>\n            <div class=\"faq-answer\">\n                <p dir=\"ltr\">Pull the official image with <code>docker pull postgres:latest<\/code>, then create a container using <code>docker run<\/code> with flags for the container name, port mapping (5432:5432), and a <code>POSTGRES_PASSWORD<\/code> environment variable.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. What&#039;s the difference between docker pull and docker run for PostgreSQL?<\/h3>\n            <div class=\"faq-answer\">\n                <p dir=\"ltr\"><code>docker pull<\/code> only downloads the image and validates it before use, while <code>docker run<\/code> creates and starts a container from that image \u2014 <code>run<\/code> will auto-pull if no image exists, but pulling first lets you work offline and confirms you&#8217;re not running malicious or corrupted images.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. How do I connect to PostgreSQL running in a Docker container?<\/h3>\n            <div class=\"faq-answer\">\n                <p dir=\"ltr\">Open a shell in the container with <code>docker exec -it &lt;container_name&gt; \"bash\"<\/code>, then connect using <code>psql -d postgres -h localhost -U postgres<\/code> \u2014 no password prompt is needed inside a trusted container shell.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">4. Why should I use a volume with my PostgreSQL Docker container?<\/h3>\n            <div class=\"faq-answer\">\n                <p dir=\"ltr\">A volume (the <code>-v<\/code> flag) maps a folder on your local machine to a directory inside the container, letting you move SQL scripts or database dump files in and out easily without extra copying steps.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">5. How do I stop and restart a PostgreSQL Docker container?<\/h3>\n            <div class=\"faq-answer\">\n                <div role=\"feed\" aria-label=\"Chat messages\" aria-describedby=\"_r_162_\">\n<div>\n<div>\n<div role=\"article\" aria-label=\"Message 4 of 4\">\n<div>\n<div>\n<div>\n<div>\n<div>\n<div>\n<div>\n<p dir=\"ltr\">Run <code>docker stop &lt;container_name&gt;<\/code> to stop it and <code>docker start &lt;container_name&gt;<\/code> to bring it back up \u2014 your data and configuration persist as long as the container isn&#8217;t deleted.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Get PostgreSQL running in Docker in minutes with this step-by-step setup guide. Learn to pull the image, run a container, set up volumes, and connect with psql.&hellip;<\/p>\n","protected":false},"author":221792,"featured_media":105920,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143523,53,143534],"tags":[4168,4170,159410,158978,4150],"coauthors":[6785],"class_list":["post-112214","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-databases","category-featured","category-postgresql","tag-database","tag-database-administration","tag-gettingstartedpostgresgrant","tag-postgresql","tag-sql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/112214","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221792"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=112214"}],"version-history":[{"count":15,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/112214\/revisions"}],"predecessor-version":[{"id":112507,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/112214\/revisions\/112507"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/105920"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=112214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=112214"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=112214"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=112214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}