<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Renan</title>
    <description>The latest articles on DEV Community by Renan (@renanbr).</description>
    <link>https://dev.to/renanbr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F235533%2F081c6833-6d18-4b5c-b656-38a9d92bd181.jpeg</url>
      <title>DEV Community: Renan</title>
      <link>https://dev.to/renanbr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renanbr"/>
    <language>en</language>
    <item>
      <title>Move Fixtures Out of src/ Folder</title>
      <dc:creator>Renan</dc:creator>
      <pubDate>Tue, 06 Oct 2020 16:37:14 +0000</pubDate>
      <link>https://dev.to/renanbr/move-fixtures-out-of-src-folder-575k</link>
      <guid>https://dev.to/renanbr/move-fixtures-out-of-src-folder-575k</guid>
      <description>&lt;p&gt;We'll see in this post an alternative place to write &lt;a href="https://github.com/doctrine/data-fixtures" rel="noopener noreferrer"&gt;fixtures&lt;/a&gt; in an &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt; application.&lt;/p&gt;




&lt;p&gt;According to the &lt;a href="https://symfony.com/doc/5.1/best_practices.html#use-the-default-directory-structure" rel="noopener noreferrer"&gt;Symfony Framework Best Practices&lt;/a&gt;, fixtures should be placed in &lt;code&gt;src/DataFixtures/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'll briefly argue against this.&lt;/p&gt;




&lt;p&gt;Development, tests, and build stuff is supposed to be discarded once the application is built. Fixtures are precisely this, a set of files for testing and/or development purposes.&lt;/p&gt;

&lt;p&gt;I would say we should place fixtures outside of &lt;code&gt;src/&lt;/code&gt; for the same reasons we write tests in the &lt;code&gt;tests/&lt;/code&gt; directory. It's better to not bloat the &lt;code&gt;src/&lt;/code&gt; with code that isn't business logic.&lt;/p&gt;

&lt;p&gt;The golden rule is to not pollute &lt;code&gt;src/&lt;/code&gt; directory with non-runtime stuff.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fixtures Under &lt;code&gt;fixtures/&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I propose to place fixtures inside the &lt;code&gt;fixtures/&lt;/code&gt; directory in the root of the project instead of &lt;code&gt;src/DataFixtures/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
└─ src/
   └─ DataFixtures/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
├─ fixtures/
└─ src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Let's make it real in your &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt; application. It may work with &lt;a href="https://github.com/symfony/demo" rel="noopener noreferrer"&gt;Symfony Demo&lt;/a&gt; as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Move Files
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Move the &lt;code&gt;src/DataFixtures/&lt;/code&gt; directory to the root;&lt;/li&gt;
&lt;li&gt;Rename it as &lt;code&gt;fixtures/&lt;/code&gt;; and&lt;/li&gt;
&lt;li&gt;Change its classes namespaces to &lt;code&gt;App\Fixtures&lt;/code&gt;&lt;sup&gt;*&lt;/sup&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, the &lt;code&gt;doctrine:fixtures:load&lt;/code&gt; command doesn't work because it can't find fixtures anymore. If you try running it you'll get this error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ERROR] Could not find any fixture services to load.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to fix it, we must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inform &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt; there is a new directory that contains classes (dev only); and&lt;/li&gt;
&lt;li&gt;Make the classes inside this directory loadable as service (dev only as well).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fix Classes Autoloading
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;"App\\Fixtures\\": "fixtures/"&lt;/code&gt;&lt;sup&gt;*&lt;/sup&gt; to the &lt;code&gt;autoload-dev&lt;/code&gt; section in &lt;code&gt;composer.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;     "autoload-dev": {
         "psr-4": {
&lt;span class="gi"&gt;+            "App\\Fixtures\\": "fixtures/",
&lt;/span&gt;             "App\\Tests\\": "tests/"
         }
     },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer dump-autoload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Services Loading
&lt;/h3&gt;

&lt;p&gt;Make the new &lt;code&gt;fixtures/&lt;/code&gt; content&lt;sup&gt;*&lt;/sup&gt; findable by &lt;a href="https://symfony.com/doc/current/service_container.html#service-container-services-load-example" rel="noopener noreferrer"&gt;loading them automaticaly&lt;/a&gt; in &lt;code&gt;config/services_dev.yaml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/services_dev.yaml&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;_defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;autowire&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;autoconfigure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="na"&gt;App\Fixtures\&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;../fixtures/*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need fixtures in another mode (e.g. &lt;code&gt;test&lt;/code&gt;), create the corresponding file (e.g. &lt;code&gt;config/services_test.yaml&lt;/code&gt;) with the same content above. &lt;/p&gt;

&lt;h2&gt;
  
  
  Fin
&lt;/h2&gt;

&lt;p&gt;The command below should work as before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/console doctrine:fixtures:load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; I use &lt;code&gt;App\Fixtures&lt;/code&gt; instead of &lt;code&gt;App\DataFixtures&lt;/code&gt; as namespace. It's up to you to adopt it or not.&lt;/p&gt;

</description>
      <category>doctrine</category>
      <category>fixtures</category>
      <category>php</category>
      <category>symfony</category>
    </item>
    <item>
      <title>Boot Symfony From Scratch With a Single Command</title>
      <dc:creator>Renan</dc:creator>
      <pubDate>Mon, 11 May 2020 13:54:31 +0000</pubDate>
      <link>https://dev.to/renanbr/boot-symfony-application-from-scratch-with-a-single-command-4c6k</link>
      <guid>https://dev.to/renanbr/boot-symfony-application-from-scratch-with-a-single-command-4c6k</guid>
      <description>&lt;p&gt;As promised:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:8000 &lt;span class="se"&gt;\&lt;/span&gt;
    solune/symfony:7.4-cli &lt;span class="se"&gt;\&lt;/span&gt;
    bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"yes n | symfony new --no-git . &amp;amp;&amp;amp; yes n | symfony serve"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Application will be available at &lt;a href="http://127.0.0.1:8000" rel="noopener noreferrer"&gt;http://127.0.0.1:8000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You're welcome.&lt;/p&gt;

&lt;p&gt;If you want to understand the command above, continue reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behind The Scenes
&lt;/h2&gt;

&lt;p&gt;As you may have noticed, the command is actually a few of well orchestred embedded commands.&lt;/p&gt;

&lt;p&gt;The base is &lt;a href="https://docs.docker.com/engine/reference/run/" rel="noopener noreferrer"&gt;&lt;code&gt;docker run&lt;/code&gt;&lt;/a&gt;. It means we are going to run &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt; inside an isolated &lt;a href="https://www.docker.com/resources/what-container" rel="noopener noreferrer"&gt;container&lt;/a&gt;. That's why we don't need enything else as requirement.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.docker.com/engine/reference/run/#foreground" rel="noopener noreferrer"&gt;&lt;code&gt;docker run -it&lt;/code&gt;&lt;/a&gt; options provide us a better bash experience with an interactive shell.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.docker.com/engine/reference/run/#clean-up---rm" rel="noopener noreferrer"&gt;&lt;code&gt;docker run --rm&lt;/code&gt;&lt;/a&gt; option automatically removes the container when it exits.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.docker.com/get-started/overview/#images" rel="noopener noreferrer"&gt;image&lt;/a&gt; selected is &lt;a href="https://hub.docker.com/r/solune/symfony" rel="noopener noreferrer"&gt;solune/symfony&lt;/a&gt;, one of my favorites. This image contains almost everything we need to work with &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt;: some PHP extensions, &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt;, &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;, and &lt;a href="https://symfony.com/download" rel="noopener noreferrer"&gt;Symfony CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once the container is running, we can install and serve an application. We  run actually a script inside the container, thanks to the pair &lt;a href="https://docs.docker.com/engine/reference/run/" rel="noopener noreferrer"&gt;&lt;code&gt;docker run&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Invoking-Bash" rel="noopener noreferrer"&gt;&lt;code&gt;bash -c&lt;/code&gt; option&lt;/a&gt;. The script we run inside the container is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yes n | symfony new --no-git .
yes n | symfony serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands contain &lt;code&gt;yes no&lt;/code&gt;. This trick prevents us to be prompted for updating &lt;a href="https://symfony.com/download" rel="noopener noreferrer"&gt;Symfony CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;symfony new&lt;/code&gt; command carries yet the &lt;code&gt;--not-git&lt;/code&gt; option. This command performs a couple of tasks, which includes the project git set up and an initial commit. It's great, but it doesn't work unless we set up our &lt;a href="https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup#_your_identity" rel="noopener noreferrer"&gt;git identity&lt;/a&gt;. Remember we're inside a container. Adding this option we skip these actions.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;symfony serve&lt;/code&gt; starts the web server at &lt;code&gt;localhost:8000&lt;/code&gt; that serves our &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt; application. Remember, we are inside the container.&lt;/p&gt;

&lt;p&gt;Lastly, the &lt;code&gt;docker run -p 8000:8000&lt;/code&gt; option. This makes the application available for us. This is mandatory because the container's ports aren't reachable from outside unless we ask for it. Note the &lt;code&gt;symfony serve&lt;/code&gt; command serves the application under the port &lt;code&gt;8000&lt;/code&gt;, but inside the container. Thanks to the &lt;a href="https://docs.docker.com/engine/reference/run/#expose-incoming-ports" rel="noopener noreferrer"&gt;docker port mapping&lt;/a&gt;, we can link a port into the container for us. In this case we use the same port number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It's all about saving time. It's not about a smart shortcut. It's neither about a long script that performs boring tasks.&lt;/p&gt;

&lt;p&gt;By simply using &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; we can dive immediately into a more pleasant context. The trick is to know and pick the best-fit start point. In this case I've choose &lt;a href="https://hub.docker.com/r/solune/symfony" rel="noopener noreferrer"&gt;solune/symfony&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>php</category>
      <category>docker</category>
    </item>
    <item>
      <title>Controlling Service Readiness in Docker Compose</title>
      <dc:creator>Renan</dc:creator>
      <pubDate>Tue, 24 Mar 2020 22:43:56 +0000</pubDate>
      <link>https://dev.to/renanbr/controlling-service-readiness-in-docker-compose-4dfm</link>
      <guid>https://dev.to/renanbr/controlling-service-readiness-in-docker-compose-4dfm</guid>
      <description>&lt;p&gt;TL;DR Add &lt;a href="https://hub.docker.com/r/dokku/wait" rel="noopener noreferrer"&gt;dokku/wait&lt;/a&gt; as a service, then run &lt;code&gt;wait -c service:port&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;If you use &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;, you probably have already tried to request a service that isn't ready, despite the container is running.&lt;/p&gt;

&lt;p&gt;Actually "running" and "ready" are two different concepts from &lt;a href="https://docs.docker.com/compose/startup-order/" rel="noopener noreferrer"&gt;Docker's point of view&lt;/a&gt;. "Running" refers to the container state. "Ready" refers to the service running inside it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can control the order of service startup and shutdown with the depends_on option. (...) However, for startup Compose does not wait until a container is "ready" only until it’s running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose/startup-order/" rel="noopener noreferrer"&gt;https://docs.docker.com/compose/startup-order/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reproducing The Problem
&lt;/h2&gt;

&lt;p&gt;To illustrate the problem, let's run some SQL command against a &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; instance just after starting it as a &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yaml&lt;/span&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:12&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3cr3t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;docker-compose.yaml&lt;/a&gt; file above, if we run these commands sequentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
docker-compose &lt;span class="nb"&gt;exec &lt;/span&gt;postgres psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"SELECT NOW()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll probably get this output error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql: error: could not connect to server: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error is due to the fact we try to run a SQL before the &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; is ready.&lt;/p&gt;

&lt;p&gt;We therefore need to find a way to be sure the service is ready before making requests to it. That's make sense, but how to fix it?&lt;/p&gt;

&lt;p&gt;Note that this problem may also happen to other services, because they follow the same pattern: container is running but the service isn't ready. Here a list of outputs for some popular services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.elastic.co/elasticsearch/" rel="noopener noreferrer"&gt;Elasticsearch&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Failed connect to elasticsearch:9200; Connection refused&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;MySQL&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://www.rabbitmq.com/" rel="noopener noreferrer"&gt;RabbitMQ&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Error: unable to perform an operation on node 'rabbit@a1b2c3d4e5f6'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Could not connect to Redis at redis:6379: Connection refused&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;We can solve this by (1) adding &lt;a href="https://hub.docker.com/r/dokku/wait" rel="noopener noreferrer"&gt;dokku/wait&lt;/a&gt; as a service in the &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;docker-compose.yaml&lt;/a&gt;, then (2) asking it to watch the service we want.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/r/dokku/wait" rel="noopener noreferrer"&gt;dokku/wait&lt;/a&gt; is a (...) &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; utility that blocks until another container is accepting TCP connections, and errors-out if it cannot connect within a given timeout.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/dokku/docker-wait" rel="noopener noreferrer"&gt;https://github.com/dokku/docker-wait&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 1: Add &lt;a href="https://hub.docker.com/r/dokku/wait" rel="noopener noreferrer"&gt;dokku/wait&lt;/a&gt; as a service
&lt;/h3&gt;

&lt;p&gt;Let's change the &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;docker-compose.yaml&lt;/a&gt; file by adding a new &lt;code&gt;wait&lt;/code&gt; service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yaml&lt;/span&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:12&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3cr3t&lt;/span&gt;

    &lt;span class="na"&gt;wait&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dokku/wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Ask &lt;a href="https://hub.docker.com/r/dokku/wait" rel="noopener noreferrer"&gt;dokku/wait&lt;/a&gt; to watch the target service
&lt;/h3&gt;

&lt;p&gt;The new &lt;code&gt;wait&lt;/code&gt; service we added to the &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;docker-compose.yaml&lt;/a&gt; file is able to reach any service in the stack by giving its name and its exposed port (e.g. &lt;code&gt;postgres:5432&lt;/code&gt;) thanks to the &lt;a href="https://docs.docker.com/compose/networking/" rel="noopener noreferrer"&gt;network set up by Docker Composer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can then ask it to block until the database get ready.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
docker-compose run &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; postgres:5432
docker-compose &lt;span class="nb"&gt;exec &lt;/span&gt;postgres psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"SELECT NOW()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Result: SQL commands will work as expected
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;wait -c postgres:5432&lt;/code&gt; command will block for some seconds the &lt;code&gt;psql -U postgres -c "SELECT NOW()"&lt;/code&gt; execution. That's why the SQL will work as expected.&lt;/p&gt;

&lt;p&gt;Furthermore, we can wait for multiples services at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose run &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; mysql:3306,redis:6379,rabbitmq:5672,elasticsearch:9200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are other approaches&lt;sup&gt;1&lt;/sup&gt; to solve this problem, but they assume we have to install some script into the host machine or into each dependent service.&lt;/p&gt;

&lt;p&gt;Adopting &lt;a href="https://hub.docker.com/r/dokku/wait" rel="noopener noreferrer"&gt;dokku/wait&lt;/a&gt; as suggested here is less intrusive because it's not needed to install a script on our machine neither on docker services stack.&lt;/p&gt;

&lt;p&gt;Tip: We can even apply this to an existing project via &lt;a href="https://docs.docker.com/compose/extends/" rel="noopener noreferrer"&gt;docker-compose.override.yaml&lt;/a&gt; without changing anything in the project itself.&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; &lt;a href="https://github.com/vishnubob/wait-for-it" rel="noopener noreferrer"&gt;wait-for-it&lt;/a&gt;, &lt;a href="https://github.com/jwilder/dockerize" rel="noopener noreferrer"&gt;dockerize&lt;/a&gt;, &lt;a href="https://github.com/Eficode/wait-for" rel="noopener noreferrer"&gt;wait-for&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
