<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://mehmandarov.com/tag/containers/feed.xml" rel="self" type="application/atom+xml"/><link href="https://mehmandarov.com/tag/containers/" rel="alternate" type="text/html"/><updated>2024-03-30T10:50:00+01:00</updated><id>https://mehmandarov.com/tag/containers/feed.xml</id><title type="html">Rustam Mehmandarov - tag: containers</title><subtitle type="text">Posts tagged &quot;containers&quot; on Rustam Mehmandarov.</subtitle><author><name>Rustam Mehmandarov</name></author><entry><title type="html">Multiplying The Developer Joy: Multiple Quarkus Containers + Simultaneous Remote Development Sessions</title><link href="https://mehmandarov.com/remote-dev-mode-quarkus/" rel="alternate" type="text/html" title="Multiplying The Developer Joy: Multiple Quarkus Containers + Simultaneous Remote Development Sessions"/><published>2024-03-30T10:50:00+01:00</published><updated>2024-03-30T10:50:00+01:00</updated><id>https://mehmandarov.com/remote-dev-mode-quarkus</id><content type="html" xml:base="https://mehmandarov.com/remote-dev-mode-quarkus/"><![CDATA[<p><em>Running several simultaneous Quarkus app containers on your machine with the Quarkus&#8217; remote development mode activated presents some challenges. Let&#8217;s have a look at how we can fix this.</em></p>

<ul>
  <li><a href="#introduction">Introduction</a></li>
  <li><a href="#setup">Setup</a></li>
  <li><a href="#conclusion">Conclusion</a></li>
</ul>

<h2 id="introduction">Introduction</h2>

<p>The built-in <a href="https://quarkus.io/guides/maven-tooling#dev-mode/">development mode</a> for Quarkus is a great functionality that lets you update the application code, resources, and configurations. Setting it up is a great way to develop your applications <em>locally</em>, as you can immediately see the changes reflected in your application.</p>

<p>Furthermore, we have a <a href="https://quarkus.io/guides/maven-tooling#remote-development-mode">remote development mode</a>, which lets you make changes to local files immediately available in a containerized environment. Remote development mode works excellently if the container runs in a local Docker or remote containerized environment.</p>

<p>However, running several simultaneous containers with the remote development mode on, mapped to the same domain, may result in warnings and erratic behavior from the client side.</p>

<h2 id="setup">Setup</h2>

<p>Imagine a setup where you are running a set of containers, for example, using <code class="language-plaintext highlighter-rouge">docker-compose</code> and mapping them all to <code class="language-plaintext highlighter-rouge">my.cluster.host.com</code> (or even <code class="language-plaintext highlighter-rouge">localhost</code>)through several ports:</p>

<p><img src="/assets/images/posts-images/2024-03-30-microservices.png" alt="Microservice Setup" /></p>
<figcaption class="caption">Microservice Setup Example</figcaption>

<p>First, you will need to update <code class="language-plaintext highlighter-rouge">quarkus.live-reload.url</code> in the properties for all the apps (see <a href="https://quarkus.io/guides/maven-tooling#remote-development-mode">docs</a> on where and how to do this). Update the settings to the correct domain and port (in our case, it is <code class="language-plaintext highlighter-rouge">8080</code>, <code class="language-plaintext highlighter-rouge">8081</code>, or <code class="language-plaintext highlighter-rouge">8082</code>):</p>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">quarkus.live-reload.url</span><span class="p">=</span><span class="s">http://localhost:8081</span>
</code></pre></div></div>

<p>Next, try starting your containers with the remote development mode enabled and connect to the application from a terminal or an IDE. For the second and the consecutive applications, the attempts to establish a connection you will see the following message in the logs:</p>

<pre><code class="language-commandline">$&gt; ./mvnw quarkus:remote-dev -Dquarkus.profile=dev

&lt; ... &gt;

[WARNING] Changed debug port to 57409 because of a port conflict
Listening for transport dt_socket at address: 57409

&lt; ... &gt;
</code></pre>

<p><em><strong>Note:</strong> Fallback ports will be random and may vary from the one above.</em></p>

<p>This setup will break the remote reloading from the terminal on the client side (i.e., your IDE). Two or more of your client applications now see that the default port <code class="language-plaintext highlighter-rouge">50005</code> for a remote debug is in use and start with a new, random port.</p>

<p>The simple fix is to update the debug ports for all other applications to something other than <code class="language-plaintext highlighter-rouge">5005</code>, such as <code class="language-plaintext highlighter-rouge">6006</code> and <code class="language-plaintext highlighter-rouge">6007</code>. Custom debug ports can be set in the <code class="language-plaintext highlighter-rouge">pom.xml</code> files, under <code class="language-plaintext highlighter-rouge">quarkus-maven-plugin</code>, for each of the applications that require this update:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;build&gt;</span>
  <span class="nt">&lt;plugins&gt;</span>
    <span class="nt">&lt;plugin&gt;</span>
      <span class="nt">&lt;groupId&gt;</span>io.quarkus.platform<span class="nt">&lt;/groupId&gt;</span>
      <span class="nt">&lt;artifactId&gt;</span>quarkus-maven-plugin<span class="nt">&lt;/artifactId&gt;</span>
      <span class="nt">&lt;version&gt;</span>${quarkus.platform.version}<span class="nt">&lt;/version&gt;</span>
      <span class="c">&lt;!-- ADD THE CONFIGURATION MENTIONED BELOW THIS LINE --&gt;</span>
      <span class="nt">&lt;configuration&gt;</span>
        <span class="nt">&lt;debug&gt;</span>6006<span class="nt">&lt;/debug&gt;</span>
      <span class="nt">&lt;/configuration&gt;</span>
...
</code></pre></div></div>

<p>You can choose whether to update the debug ports for all applications in the cluster or for all applications except one, which will get the default port.</p>

<p>Now, you will need to rebuild your apps and re-initiate the remote development mode for each container. And, voil&#224;, everything works!</p>

<p><strong><em>One last note</em></strong>: Please ensure you do not use the remote development functionality in the production environment.</p>

<h2 id="conclusion">Conclusion</h2>
<p>A tiny config update brings back the development joy of using remote development mode for more than one container simultaneously.</p>

<p><strong><em>Happy coding!</em></strong></p>]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Running several simultaneous Quarkus app containers on your machine with the Quarkus&#8217; remote development mode activated presents some challenges. Let&#8217;s have a look at how we can fix this.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/container-ship.jpeg"/><category term="blog"/><category term="english"/><category term="java"/><category term="containers"/><category term="quarkus"/><category term="docker"/></entry><entry><title type="html">Disposable Docker Containers</title><link href="https://mehmandarov.com/disposable-docker-containers/" rel="alternate" type="text/html" title="Disposable Docker Containers"/><published>2019-01-01T11:01:00+01:00</published><updated>2019-01-01T11:01:00+01:00</updated><id>https://mehmandarov.com/disposable-docker-containers</id><content type="html" xml:base="https://mehmandarov.com/disposable-docker-containers/"><![CDATA[<p><em>Disposable containers may sound like a tautology. However, here we will be looking into single-use, ephemeral containers &#8211; even in the context of the containers &#8211; that are used for building and testing applications, and disposing of them shortly after.</em></p>

<hr />

<p>Containers are something that we use to run our applications and, normally, we dispose of the whole container when we build a new version of the application or need to upgrade something in the setup. This means that containers are generally having a short lifespan.</p>

<p>However, in this case, I want to show you how to build something that exists for an even shorter period of time and that can be used as an alternative to a local setup for building and testing applications locally before pushing it to test, staging, production, etc.</p>

<p>This is a simplified example of what is being done on a much bigger scale with moving your CI/CD pipelines to such disposable containers, and with libraries like <a href="https://www.testcontainers.org/">Testcontainers</a>.</p>

<p>In this case, I would like to show you how to setup Jekyll applications, but this can be easily applied to any kind of applications written in any of your favorite languages, like Java or Python. Until recently, I have been running a Jekyll installation locally with all dependencies installed on my machine. However, it has been a bit challenging when moving between machines and reinstalling operating systems. To simplify the process, I decided to containerize the local build and test processes.</p>

<p>I wanted the following:</p>

<ul>
  <li>To build my code from and to the local folder on my (host) machine</li>
  <li>Run the application (in this case this blog) from a local folder on my (host) machine</li>
  <li>Avoid setting up the environment, or have a minimal and portable setup</li>
  <li>Avoid environment clean-up &#8211; I didn&#8217;t want to hold on to the unnecessary containers and container images</li>
</ul>

<h2 id="tldr-the-solution"><em><strong>TL;DR</strong></em>: The solution</h2>
<p><em><strong>(see next section for the explanation)</strong></em></p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">export </span><span class="nv">JEKYLL_VERSION</span><span class="o">=</span>3.8
<span class="nv">$ </span>docker run <span class="nt">--rm</span> <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="se">\</span>
       <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll build
<span class="nv">$ </span>docker run <span class="nt">--name</span> newblog <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="nt">-p</span> 4000:4000 <span class="se">\</span>
       <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll serve <span class="nt">--watch</span> <span class="nt">--drafts</span></code></pre></figure>

<h2 id="explanation--line-by-line">Explanation &#8211; line by line</h2>

<p>So, let&#8217;s take a closer look at each of the lines:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">1: <span class="nb">export </span><span class="nv">JEKYLL_VERSION</span><span class="o">=</span>3.8</code></pre></figure>

<p>Just setting up versions that will be used later &#8211; a bit of housekeeping. Nothing exciting here.</p>

<hr />

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">2: docker run <span class="nt">--rm</span> <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="se">\</span>
        <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll build</code></pre></figure>

<p>Here, we build the code and output it to the same disk volume as the source code, i.e. the volume that is shared with my host machine. Now I have the built version on my machine without the hassle of setting up the local build environment. In addition to that, I will be doing some clean-up, by deleting the build container after the build job is finished.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--rm</code> &#8211; just execute the command and clean-up (remove the container, file system, etc.)</li>
  <li><code class="language-plaintext highlighter-rouge">--volume</code> &#8211; mapping the current directory to <code class="language-plaintext highlighter-rouge">/srv/jekyll</code> in the container</li>
  <li><code class="language-plaintext highlighter-rouge">-it</code> instructs Docker to allocate a pseudo-TTY connected to the container&#8217;s stdin; creating an interactive shell in the container
    <ul>
      <li><code class="language-plaintext highlighter-rouge">-i</code> &#8211; attach container&#8217;s STDIN</li>
      <li><code class="language-plaintext highlighter-rouge">-t</code> &#8211; allocate a pseudo-TTY</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">jekyll/jekyll:$JEKYLL_VERSION</code> &#8211; Docker <a href="https://github.com/envygeeks/jekyll-docker/blob/master/README.md">image</a> to use and the tag</li>
  <li><code class="language-plaintext highlighter-rouge">jekyll build</code> &#8211; command to run</li>
</ul>

<hr />

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">3. docker run <span class="nt">--name</span> newblog <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="nt">-p</span> 4000:4000 <span class="se">\</span>
        <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll serve <span class="nt">--watch</span> <span class="nt">--drafts</span></code></pre></figure>

<p>This will create another container that will be running our application. Here we will need to add a few other parameters &#8211; like mapping the container ports to the ports on the local machine and giving the container a name.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--name newblog</code> &#8211; give your container a name</li>
  <li><code class="language-plaintext highlighter-rouge">--volume</code> &#8211; mapping the current directory to <code class="language-plaintext highlighter-rouge">/srv/jekyll</code> in the container</li>
  <li><code class="language-plaintext highlighter-rouge">-p</code> &#8211; bind port 4000 of the container to TCP port 4000 (<code class="language-plaintext highlighter-rouge">-p host_machine:container</code>)</li>
  <li><code class="language-plaintext highlighter-rouge">-it</code> instructs Docker to allocate a pseudo-TTY connected to the container&#8217;s stdin; creating an interactive shell in the container
    <ul>
      <li><code class="language-plaintext highlighter-rouge">-i</code> &#8211; attach container&#8217;s STDIN</li>
      <li><code class="language-plaintext highlighter-rouge">-t</code> &#8211; allocate a pseudo-TTY</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">jekyll/jekyll:$JEKYLL_VERSION</code> &#8211; Docker <a href="https://github.com/envygeeks/jekyll-docker/blob/master/README.md">image</a> to use and the tag</li>
  <li><code class="language-plaintext highlighter-rouge">jekyll serve --watch --drafts</code> &#8211; command to run</li>
</ul>

<p>Now you can stop the container with <code class="language-plaintext highlighter-rouge">CTRL+c</code>, and restart it again with:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>docker start newblog <span class="nt">-i</span></code></pre></figure>

<p>If you don&#8217;t want the container being persistent on your system, you can simply add <code class="language-plaintext highlighter-rouge">--rm</code> as in the previous command:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>docker run <span class="nt">--rm</span> <span class="nt">--name</span> newblog <span class="nt">--volume</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/srv/jekyll"</span> <span class="nt">-p</span> 4000:4000 <span class="se">\</span>
       <span class="nt">-it</span> jekyll/jekyll:<span class="nv">$JEKYLL_VERSION</span> jekyll serve <span class="nt">--watch</span> <span class="nt">--drafts</span></code></pre></figure>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Using single-use, ephemeral Docker containers for building and testing applications locally.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/containers.jpg"/><category term="blog"/><category term="containers"/><category term="docker"/><category term="jekyll"/><category term="field notes"/><category term="english"/></entry></feed>
