<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Practical Systems Lab on Medium]]></title>
        <description><![CDATA[Stories by Practical Systems Lab on Medium]]></description>
        <link>https://medium.com/@PracticalSysLab?source=rss-749046693184------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*B70UzYRw0u06VSb2uBSwPw.png</url>
            <title>Stories by Practical Systems Lab on Medium</title>
            <link>https://medium.com/@PracticalSysLab?source=rss-749046693184------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 22:13:01 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@PracticalSysLab/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Why Docker Compose depends_on Does Not Fix Your Database Connection Error]]></title>
            <link>https://medium.com/@PracticalSysLab/why-docker-compose-depends-on-does-not-fix-your-database-connection-error-10e0502730f0?source=rss-749046693184------2</link>
            <guid isPermaLink="false">https://medium.com/p/10e0502730f0</guid>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[docker-compose]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[troubleshooting]]></category>
            <dc:creator><![CDATA[Practical Systems Lab]]></dc:creator>
            <pubDate>Wed, 11 Nov 2026 22:20:52 GMT</pubDate>
            <atom:updated>2026-11-11T22:31:20.115Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AJv-Idyjt9N5xZS9.png" /></figure><p>You use Docker Compose to start a database and an application, with depends_on defining the dependency between them. Yet the application reports a database connection error. You configured the database to start first, but the application only connects when you restart it a little later.</p><p>Compose is following your configuration. When you list only a service name under depends_on, it waits for <strong>the database container to start</strong>. It does not wait for the database to accept connections.</p><p>We’ll use PostgreSQL to see the difference between controlling startup order and waiting until the database can accept connections.</p><h3>Listing a service under depends_on only controls startup order</h3><p>Here is a common configuration:</p><pre>depends_on:<br>  - db</pre><p>This starts the db container before the application. The condition used by this form is service_started. Writing that condition explicitly gives you the same startup behavior:</p><pre>depends_on:<br>  db:<br>    condition: service_started</pre><p>condition specifies the state a dependency must reach before Compose proceeds. service_started means “continue once the container has started.”</p><p>Both forms wait only for the container to start, whether or not db has a health check. To wait for a successful health check, you need condition: service_healthy, which we&#39;ll use below. The <a href="https://docs.docker.com/reference/compose-file/services/#depends_on">Compose specification</a> defines a service-name-only dependency and service_started as equivalent conditions.</p><p>But a running PostgreSQL container is not necessarily ready for connections. On its first start, PostgreSQL takes time to initialize its data directory and run initialization scripts. Recovery may also be needed after a restart. If the application tries to connect while this work is still in progress, the connection fails.</p><p>The startup order can be correct while the database is still getting ready. <a href="https://docs.docker.com/compose/how-tos/startup-order/">Docker’s documentation</a> makes the same distinction between a running container and a ready service.</p><p>To wait for readiness, use healthcheck together with condition: service_healthy. A healthcheck periodically runs a command inside the container and uses its result to assess the container&#39;s health. With service_healthy, Compose waits for the dependency to pass that check and become healthy before starting the dependent service. Here, the check tests whether the database accepts connections.</p><p><strong>Adding a </strong><strong>healthcheck alone is not enough.</strong> If depends_on still lists only the service name, Compose continues to wait only for startup. You need both healthcheck and condition: service_healthy.</p><h3>Try it with a connection test container</h3><p>There is no need to build an application just to test a database connection. Instead, we’ll use a probe container that runs SELECT 1; and exits.</p><p>This example uses PostgreSQL 16. It assumes Docker Engine and the Compose plugin are installed and that you can run docker compose. If you have used docker compose up and down, you can follow along without prior knowledge of health checks. We&#39;ll run Compose on a single machine; Docker Swarm, which can distribute containers across multiple machines, is outside the scope of this example.</p><p>The example was tested on November 12, 2026, with Ubuntu 26.04.1 LTS on WSL2, Docker Engine 29.9.1, Docker Compose 5.6.0, and PostgreSQL 16.15.</p><p>Create a new working directory and save the following as compose.yaml.</p><p>We’ll use the project name depends-on-demo. Database data is stored in a named volume, so make sure you do not already have a project with that name. The password is for this experiment only; do not use it in production. The database port is not published to the host.</p><pre>services:<br>  db:<br>    image: postgres:16<br>    environment:<br>      POSTGRES_USER: demo<br>      POSTGRES_PASSWORD: local-demo-only<br>      POSTGRES_DB: demo<br>    volumes:<br>      - db-data:/var/lib/postgresql/data<br>    healthcheck:<br>      test: [&quot;CMD-SHELL&quot;, &#39;pg_isready -h 127.0.0.1 -U &quot;$${POSTGRES_USER}&quot; -d &quot;$${POSTGRES_DB}&quot;&#39;]<br>      interval: 2s<br>      timeout: 3s<br>      retries: 15<br>      start_period: 10s</pre><pre>  probe:<br>    image: postgres:16<br>    environment:<br>      PGHOST: db<br>      PGPORT: &quot;5432&quot;<br>      PGUSER: demo<br>      PGPASSWORD: local-demo-only<br>      PGDATABASE: demo<br>      PGCONNECT_TIMEOUT: &quot;3&quot;<br>    depends_on:<br>      db:<br>        condition: service_healthy<br>    command: [&quot;psql&quot;, &quot;-w&quot;, &quot;-v&quot;, &quot;ON_ERROR_STOP=1&quot;, &quot;-c&quot;, &quot;SELECT 1;&quot;]</pre><pre>volumes:<br>  db-data:</pre><p>The db service has a healthcheck, and probe depends on it with condition: service_healthy. Under the <a href="https://docs.docker.com/reference/compose-file/services/#depends_on">Compose specification</a>, startup proceeds as follows:</p><ol><li>Compose starts the db container.</li><li>The health check runs repeatedly inside db. Once the database accepts connections, the check succeeds and the container becomes healthy.</li><li>Compose starts the probe container.</li><li>probe connects to the database, runs SELECT 1;, and exits.</li></ol><p>To make connection and SQL failures visible, the psql command in probe uses -w to avoid waiting for a password prompt and -v ON_ERROR_STOP=1 to stop on SQL errors. The SQL statement to execute follows -c.</p><h3>Check connection readiness with healthcheck.test</h3><p>In the configuration above, pg_isready is the command under db → healthcheck → test. It checks whether PostgreSQL accepts connections. If it does, the command returns exit code 0 and the health check succeeds.</p><p>The -h 127.0.0.1 option makes the check connect over TCP from inside the database container. -U specifies the user, and -d specifies the database name.</p><p>The official PostgreSQL image starts a temporary server during initialization. That server accepts connections through a Unix socket, a local communication endpoint within the container. If pg_isready uses that socket, it can reach the temporary server and pass the health check. The container could then be marked healthy and probe could start before initialization has finished.</p><p>Using TCP avoids treating that temporary server as ready. This choice follows the <a href="https://github.com/docker-library/postgres/blob/master/docker-entrypoint.sh">official image’s entrypoint script</a>; it is not a universal rule for every database image. When adapting the check to another container, choose a command and connection method that actually test what “ready” means for that service.</p><h3>Start the containers</h3><p>From the directory where you saved the configuration, validate it, start the containers, and inspect their state and logs:</p><pre>docker compose -p depends-on-demo config -q<br>docker compose -p depends-on-demo up -d<br>docker compose -p depends-on-demo ps -a<br>docker compose -p depends-on-demo logs --timestamps db probe</pre><p>In the output of docker compose -p depends-on-demo ps -a, look for db to be healthy and probe to show Exited (0), meaning it finished successfully with exit code 0. In the output of logs --timestamps db probe, check that the probe log contains 1 as the result of SELECT 1;.</p><p>--timestamps adds a timestamp to each log line; it does not sort logs from different containers into chronological order. The probe logs may appear before the db logs. Compare the timestamps on the lines rather than their position in the output to determine which event happened first.</p><p>up -d does not wait for probe to finish. If probe is still running, wait briefly and run the same ps -a and log commands again.</p><p>Since probe runs just one SQL statement, an exited container is expected.</p><h3>Command options</h3><p>Here is a quick reference for the options above. If you already know them, skip ahead.</p><p>OptionPurpose-p depends-on-demoSets the Compose project name. This -p does not specify a portconfig -qValidates the configuration without printing it on successup -dStarts the containers in the backgroundps -aIncludes exited containers in the listinglogs --timestampsAdds a timestamp to each log line</p><h3>Compare with a configuration that only waits for startup</h3><p>Here is the full configuration for comparison. It keeps the healthcheck on db and changes only probe&#39;s depends_on to the service-name-only form.</p><pre>services:<br>  db:<br>    image: postgres:16<br>    environment:<br>      POSTGRES_USER: demo<br>      POSTGRES_PASSWORD: local-demo-only<br>      POSTGRES_DB: demo<br>    volumes:<br>      - db-data:/var/lib/postgresql/data<br>    healthcheck:<br>      test: [&quot;CMD-SHELL&quot;, &#39;pg_isready -h 127.0.0.1 -U &quot;$${POSTGRES_USER}&quot; -d &quot;$${POSTGRES_DB}&quot;&#39;]<br>      interval: 2s<br>      timeout: 3s<br>      retries: 15<br>      start_period: 10s</pre><pre>  probe:<br>    image: postgres:16<br>    environment:<br>      PGHOST: db<br>      PGPORT: &quot;5432&quot;<br>      PGUSER: demo<br>      PGPASSWORD: local-demo-only<br>      PGDATABASE: demo<br>      PGCONNECT_TIMEOUT: &quot;3&quot;<br>    depends_on:<br>      - db<br>    command: [&quot;psql&quot;, &quot;-w&quot;, &quot;-v&quot;, &quot;ON_ERROR_STOP=1&quot;, &quot;-c&quot;, &quot;SELECT 1;&quot;]</pre><pre>volumes:<br>  db-data:</pre><p>Create a separate working directory for this comparison and save the configuration there as compose.yaml. From that directory, start it with a different project name. This creates a fresh volume for initialization, keeping it separate from the data used in the first experiment.</p><pre>docker compose -p depends-on-short-demo up -d<br>docker compose -p depends-on-short-demo ps -a<br>docker compose -p depends-on-short-demo logs --timestamps db probe</pre><p>The health check still runs, but Compose starts probe without waiting for it to pass.</p><p>This does not mean the connection will always fail. If PostgreSQL initializes quickly, it may be ready by the time probe connects. The same can happen with an already initialized volume.</p><p>Even if the query succeeds, <strong>Compose did not wait for the database to become ready</strong>.</p><h3>Does healthy mean the connection will succeed?</h3><p>A database can accept connections and still reject an incorrect username or password. pg_isready checks whether the server accepts connections; <strong>it does not verify the application&#39;s credentials</strong>.</p><p>The <a href="https://www.postgresql.org/docs/16/app-pg-isready.html">PostgreSQL documentation</a> notes that a correct username or password is not required to determine the server’s status.</p><p>That is why this example runs SELECT 1; from probe as a separate check. The query tests service-name resolution, a connection over the network, authentication, and SQL execution. The options used here are documented in the <a href="https://www.postgresql.org/docs/16/app-psql.html">psql reference</a>.</p><p>Even a successful SELECT 1; does not establish that the application&#39;s tables or required permissions are in place. If the application needs database migrations, check that they have finished as well. Compose also provides service_completed_successfully, a condition that waits for another service to finish successfully.</p><p>Being able to connect to the database and being able to perform the application’s work are separate checks.</p><h3>If you get an error</h3><p>Startup timing is only one possible cause of a connection error. Use the error message to decide what to check.</p><p>SymptomWhat to checkConnection refusedDatabase state, listening address, and destination portHostname cannot be resolvedService name and the networks the containers belong toPassword authentication failedCredentials and database authentication settingsTable does not existTarget database, schema, and migrations</p><p>These are starting points for investigation. A symptom does not always map to a single cause.</p><p>Also check the connection address. In this example, probe connects to db:5432. If you use localhost, it tries to connect to probe itself rather than the database container.</p><p>Containers on the same Compose network use the service name and the container-side port. As <a href="https://docs.docker.com/compose/how-tos/networking/">Docker’s networking documentation</a> explains, you do not need to publish the database port to the host. Publishing a port will not fix an incorrect connection address.</p><h3>Connection failures after startup need a separate solution</h3><p>service_healthy handles readiness at startup. It does not make Compose manage application connections if they break later.</p><p>For example, a database restart can invalidate connections the application is holding. The application needs a way to reconnect.</p><p>Check the behavior of your database driver and connection pool. For temporary failures, retry with a defined interval and a limit on attempts or total time. Do not retry indefinitely when the error is persistent, such as an incorrect password.</p><p><strong>Reconnecting and retrying a SQL statement are different operations.</strong> If the connection drops just after a write, you may not know whether the transaction was committed. Consider whether repeating that write could create duplicate data.</p><p>In Compose 2.17.0 and later, you can set restart: true under db in the application&#39;s depends_on configuration. This lets Compose restart the dependent application when it updates or explicitly restarts the database, for example with docker compose restart db. It does not apply when a crashed container is automatically restarted, and it does not replace application-level reconnection logic.</p><p>You can also add sleep 10 before starting an application. That may work in some environments, but the connection will fail again if the database needs more than ten seconds. The condition to wait for is the database accepting connections, rather than a fixed amount of elapsed time.</p><h3>Clean up</h3><p>When you finish, choose one of the following commands depending on whether you want to keep the database data. Run it from the directory where you saved the configuration.</p><p>To keep the data, remove only the containers and network:</p><pre>docker compose -p depends-on-demo down</pre><p>If you no longer need the experiment’s database data, run down -v instead of the plain down above. This removes the database volume along with the containers and network.</p><p><strong>down -v deletes the data in the volume.</strong> Check that you are in the experiment&#39;s working directory and using its project name before running it.</p><pre>docker compose -p depends-on-demo down -v</pre><p>If you also ran the comparison, clean it up from its own working directory using the same cleanup command with the project name changed to depends-on-short-demo.</p><p>When depends_on does not resolve a database connection error, first check whether it waits only for startup or for the database to become healthy. Authentication errors, missing schema, and disconnections after startup each need their own diagnosis and response.</p><p><em>Originally published at </em><a href="https://practicalsyslab.substack.com/p/why-docker-compose-depends_on-does"><em>https://practicalsyslab.substack.com</em></a><em> on November 11, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10e0502730f0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Knowledge Still Matters When AI Can Give Us Answers]]></title>
            <link>https://medium.com/@PracticalSysLab/why-knowledge-still-matters-when-ai-can-give-us-answers-85172f933991?source=rss-749046693184------2</link>
            <guid isPermaLink="false">https://medium.com/p/85172f933991</guid>
            <category><![CDATA[critical-thinking]]></category>
            <category><![CDATA[education]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[knowledge]]></category>
            <dc:creator><![CDATA[Practical Systems Lab]]></dc:creator>
            <pubDate>Tue, 10 Nov 2026 20:43:46 GMT</pubDate>
            <atom:updated>2026-11-11T12:57:55.327Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dzAmbRlMN_ZaAhhM.png" /></figure><p>Ask an AI a question, and it can explain how to write a program or troubleshoot a computer problem. Does that mean we no longer need technical knowledge?</p><p>I think <strong>the knowledge we need to work out what to ask has become more important than before.</strong> AI can quickly suggest possibilities, but when we use a chat that cannot inspect our computer directly, we need to tell it what is happening.</p><p>Suppose we ask, “My computer has been slow lately. How do I fix it?”</p><p>The AI might suggest restarting it, removing unnecessary applications, or checking the available storage space. These are all reasonable starting points, but the cause is still unknown.</p><p>Now add some observations:</p><blockquote><em>Everyday tasks work normally, but copying a large file to an external USB drive takes a long time. I don’t know when the transfers became slow.</em></blockquote><p>If we know that the destination and connection can affect file transfer speed, we can recognize why we need to mention the external USB drive. Making the question more specific helps narrow down what to investigate. Still, this alone does not establish that a faulty drive is the cause. The connection, available space, and condition of the hardware need further checking.</p><p>Dealing with a problem involves at least three stages:</p><ol><li><strong>Observe:</strong> What happened, when, and under what conditions?</li><li><strong>Isolate:</strong> Does changing a condition change the behavior?</li><li><strong>Act:</strong> Test a possible cause before making a change to address it.</li></ol><p>AI is good at expanding the range of possible checks and remedies. The user still has a role in accurately observing the actual situation and deciding how much may be changed.</p><p>For example, if we ask an AI for help tidying up and it says, “You can throw this document away,” we would check whether we might need it later before discarding it. Even when a suggestion sounds plausible, we need to consider what it affects and what could happen before acting on it.</p><p>Basic knowledge helps us put names to possible causes. Even thoughts such as “It might be a connection problem,” “It might involve the destination drive,” or “Authentication might be failing” can change the quality of our questions.</p><p>That knowledge also helps us check AI-generated answers. An explanation may sound plausible, yet depend on different conditions or a different software version, making it unsuitable for our situation. We can compare it with the software’s official instructions. If we do not understand the effects of a change or how to undo it, we should check with an administrator or someone knowledgeable before proceeding.</p><p>Knowledge helps us remember answers, but it also helps us explain what we have checked and what we still do not understand.</p><p>The knowledge that helps here is not limited to expertise gained at work. Learning a broad range of subjects throughout our school years also gives us a foundation for reading AI-generated answers and thinking for ourselves.</p><p>For example, understanding ratios and percentages lets us respond to “Sales doubled” with “What was the starting amount?” Sales rising from $100 to $200 and from $10,000 to $20,000 have both doubled, but the amounts gained are different. Both statements are correct, but the difference in scale matters.</p><p>Learning to keep experimental conditions consistent in science lessons can help us recognize that, if we change several computer settings at once and the problem disappears, we still do not know which change worked. Learning to distinguish claims from supporting evidence in reading and writing classes also helps us check whether an AI’s explanation has reasons behind it or contradicts itself along the way.</p><p>In an unfamiliar field, it can be hard even to notice which parts of an explanation to question or what to ask next. That is why I think there is value in encountering a broad range of knowledge, including things whose immediate use is unclear. We do not have to remember every lesson forever. Remembering that a way of thinking exists can give us a starting point for looking into it again.</p><p>Suppose an AI tells us to restart a computer, and the symptoms improve. We may decide that’s enough for now. But knowing a little about memory and running applications can lead to further questions: “Why did restarting help?” or “What should I check if it happens again?”</p><p>Learning how one thing works through an AI’s answer can help us notice more for ourselves the next time we ask for help. We do not need to be knowledgeable from the start. Understanding unfamiliar terms one by one as we encounter problems is also a way of building knowledge.</p><p>Return to the external drive example. Suppose the AI says, “The USB connection speed is causing the slowdown.” A fluent explanation can make us feel as though the cause has been found. But knowing that the connection can affect copying speed is different from knowing that it is the cause of this particular slowdown.</p><p>A little knowledge lets us ask, “What information led to that conclusion?” or “What should we check to distinguish it from other possible causes?” If we encounter an unfamiliar term, we can start by looking up its meaning and considering whether the explanation applies to our situation.</p><p>Asking the AI for its reasons does not mean the explanation itself is correct. We need to check whether there is evidence behind it, by comparing it with official documentation or examining the actual situation. Here, too, knowledge helps us work out what to compare and what results would conflict with the explanation.</p><p>When sharing information for these checks, avoid casually pasting passwords, private keys, personal data, or confidential company documents into an AI chat. Error messages also need checking for credentials or personal information.</p><p>It is convenient to get an answer from AI straight away. But <strong>being able to judge whether to act on that answer</strong> affects the outcome. What we learned at school and what we have picked up through everyday questions both help us make that judgment.</p><p>The next time something goes wrong, try writing one line about “what I know so far” and another about “what I have not checked yet” before asking for a solution. Even that can make the conversation with AI more specific.</p><p><em>This article discusses general problem-solving habits. Before making changes to a real system, check what the changes involve and how to recover if something goes wrong.</em></p><p><em>Originally published at </em><a href="https://practicalsyslab.substack.com/p/why-knowledge-still-matters-when"><em>https://practicalsyslab.substack.com</em></a><em> on November 10, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=85172f933991" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>