<?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/docker/feed.xml" rel="self" type="application/atom+xml"/><link href="https://mehmandarov.com/tag/docker/" rel="alternate" type="text/html"/><updated>2024-03-30T10:50:00+01:00</updated><id>https://mehmandarov.com/tag/docker/feed.xml</id><title type="html">Rustam Mehmandarov - tag: docker</title><subtitle type="text">Posts tagged &quot;docker&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><entry><title type="html">Docker Command Line Survival Guide: The Absolute Basics</title><link href="https://mehmandarov.com/docker-cmd-survival-guide/" rel="alternate" type="text/html" title="Docker Command Line Survival Guide: The Absolute Basics"/><published>2017-07-27T08:23:00+02:00</published><updated>2017-07-27T08:23:00+02:00</updated><id>https://mehmandarov.com/docker-cmd-survival-guide</id><content type="html" xml:base="https://mehmandarov.com/docker-cmd-survival-guide/"><![CDATA[<p><em>A brief introduction to ten essential and absolute basic Docker commands to get you started, and keep you going in the command-line interface.</em></p>

<ul>
  <li><a href="#getting-started">Getting Started</a></li>
  <li><a href="#commands-files-and-folders-inside-a-container">Commands, Files, and Folders Inside a Container</a></li>
  <li><a href="#cleanup">Cleanup</a></li>
</ul>

<hr />

<p>In this post, I decided to share some of the basic commands you might need to get started with Docker. This is neither an extensive list of the commands available, nor all of the commands you might need. This is merely me sharing a prettified list of my cheat sheet for Docker basics with <em>you</em>.</p>

<h2 id="getting-started">Getting Started</h2>

<p>Before we get started, it might be a good idea to note that all of the commands below are written without <code class="language-plaintext highlighter-rouge">sudo</code>. If your installation is not running without <code class="language-plaintext highlighter-rouge">sudo</code> (assuming that you are running Linux), you might want to check out the <a href="https://docs.docker.com/engine/installation/linux/linux-postinstall/" target="_blank">post-installation guide for Linux</a> in the Docker docs.</p>

<h4 id="1-check-if-everything-works">1. Check if Everything Works</h4>

<p>First things first, you can use this simple command to check that your installation is fine. <strong><em>Note:</em></strong> Make sure you have right CPU architecture for your images. Raspberry Pi (ARM) things will not run on x86 architecture, and vice versa.</p>

<p>For x86:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker run docker/whalesay cowsay Hello World!</code></pre></figure>

<p>For Raspberry Pi / AMD:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker run <span class="nt">-d</span> <span class="nt">-p</span> 80:80 hypriot/rpi-busybox-httpd</code></pre></figure>

<p><img src="/assets/images/posts-images/2017-07-27_helloworld-rpi.png" alt="Hello World" class="bigger-image" /></p>

<h4 id="2-list-containers">2. List Containers</h4>

<p>After creating containers, first thing you might want to do is to see what containers you have up and running. To list all running containers you can use:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker ps</code></pre></figure>

<p>This command will give you a list similar to this:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                    PORTS                NAMES
e85753d57a67        easypi/dokuwiki-arm         "/bin/sh -c 'php-f..."   1 days ago          Up 23 hours               0.0.0.0:80-&gt;80/tcp   mywiki</code></pre></figure>

<p>However, it will not show you any stopped containers. To list <em>all</em> local containers use the <code class="language-plaintext highlighter-rouge">-a</code> option:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker ps <span class="nt">-a</span></code></pre></figure>

<p>The output will be more like this (note that is shows also stopped, or even failed containers):</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                    PORTS                NAMES
573193cf1d5e        hypriot/rpi-busybox-httpd   "/bin/busybox http..."   2 days ago          Exited (0) 5 hours ago                         mytest
e85753d57a67        easypi/dokuwiki-arm         "/bin/sh -c 'php-f..."   1 days ago          Up 23 hours               0.0.0.0:80-&gt;80/tcp   mywiki</code></pre></figure>

<p>More on <code class="language-plaintext highlighter-rouge">docker ps</code> in the <a href="https://docs.docker.com/engine/reference/commandline/ps/" target="_blank">Docker docs</a>.</p>

<h4 id="3-list-images">3. List Images</h4>

<p>To list all the images available on your system, simply do this:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker images</code></pre></figure>

<h4 id="4-containers-vs-images">4. Containers vs. Images?</h4>

<p>What is the difference between containers and images, you might wonder? Well, I have a <a href="https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/" target="_blank">link</a> for you. This will hopefully help you to understand how Docker manages the data within your images and containers.</p>

<h4 id="5-starting-and-stopping-containers">5. Starting and Stopping Containers</h4>

<p>Another two basic commands &#8211;&#160;<a href="https://docs.docker.com/engine/reference/commandline/start/" target="_blank">starting</a> and <a href="https://docs.docker.com/engine/reference/commandline/stop/" target="_blank">stopping</a> containers:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker start &lt;container_id&gt;
<span class="gp">$</span><span class="w"> </span>docker stop &lt;container_id&gt;</code></pre></figure>

<p><strong><em>Note:</em></strong> The <code class="language-plaintext highlighter-rouge">docker run</code> command first creates a writeable container layer over the specified image, and then starts it using the specified command. That is, <code class="language-plaintext highlighter-rouge">docker run</code> is equivalent to the API&#8217;s <code class="language-plaintext highlighter-rouge">/containers/create</code>, and then <code class="language-plaintext highlighter-rouge">/containers/&lt;id&gt;/start</code>.</p>

<hr />

<h2 id="commands-files-and-folders-inside-a-container">Commands, Files, and Folders Inside a Container</h2>

<h4 id="6-run-any-command-from-a-container">6. Run Any Command from a Container</h4>
<p>You can <a href="https://docs.docker.com/engine/reference/commandline/exec/" target="_blank">run any command</a> in a running container just knowing its ID (or name):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker <span class="nb">exec</span> <span class="nt">-it</span> &lt;container_id_or_name&gt; <span class="nb">echo</span> <span class="s2">"Hello from container!"</span></code></pre></figure>

<h4 id="7-getting-into-containers">7. Getting Into Containers</h4>

<p>Since you can run any command, then you can (obviously) also run a shell from a container; if you have any. This will be a bit similar to running an <code class="language-plaintext highlighter-rouge">ssh</code> command to connect remotely to a regular Linux box (given you have <code class="language-plaintext highlighter-rouge">bash</code> or <code class="language-plaintext highlighter-rouge">sh</code> in the container):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker <span class="nb">exec</span> <span class="nt">-it</span> &lt;container_id_or_name&gt; bash
<span class="gp">$</span><span class="w"> </span><span class="c"># or:</span>
<span class="gp">$</span><span class="w"> </span>docker <span class="nb">exec</span> <span class="nt">-it</span> &lt;container_id_or_name&gt; sh</code></pre></figure>

<h4 id="8-copy-files-from-and-to-containers">8. Copy Files From and To Containers</h4>

<p>Another useful trick you might need is to copy some files to and from a container. Your friend here is the <code class="language-plaintext highlighter-rouge">docker cp</code> command (<a href="https://docs.docker.com/edge/engine/reference/commandline/cp/" target="_blank">link to the docs</a>):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="c"># To container:</span>
<span class="gp">$</span><span class="w"> </span>docker <span class="nb">cp </span>foo.txt &lt;container_name&gt;:/foo.txt
<span class="gp">$</span><span class="w"> </span><span class="c"># From container:</span>
<span class="gp">$</span><span class="w"> </span>docker <span class="nb">cp</span> &lt;container_name&gt;:/foo.txt foo.txt</code></pre></figure>

<hr />

<h2 id="cleanup">Cleanup</h2>

<p>After playing round with all the images and containers, you might realize that you have quite a collection of these on your drive, just taking up space.</p>

<h4 id="9-remove-containers">9. Remove Containers</h4>

<p>To remove the unused or unwanted containers, you can run the <code class="language-plaintext highlighter-rouge">docker rm</code> command with the IDs of those images. The IDs can be retrieved with the <code class="language-plaintext highlighter-rouge">docker ps -a</code> command, mentioned above.</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker <span class="nb">rm</span> &lt;container_id&gt;</code></pre></figure>

<h4 id="10-remove-images">10. Remove Images</h4>

<p>The <code class="language-plaintext highlighter-rouge">docker rmi</code> command followed by the IDs of images will help you to remove the unused or unwanted images. The abovementioned <code class="language-plaintext highlighter-rouge">docker images</code> command will help you finding the correct IDs for the images in question.</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker rmi &lt;container_id&gt;</code></pre></figure>

<p><em>Have fun!</em></p>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Ten essential Docker commands to get you started with the command-line interface.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/street-art-container_small.jpeg"/><category term="blog"/><category term="docker"/><category term="command line"/><category term="field notes"/><category term="english"/></entry><entry><title type="html">Start Docker Containers Automatically</title><link href="https://mehmandarov.com/start-docker-containers-automatically/" rel="alternate" type="text/html" title="Start Docker Containers Automatically"/><published>2017-07-09T10:50:00+02:00</published><updated>2017-07-09T10:50:00+02:00</updated><id>https://mehmandarov.com/start-docker-containers-automatically</id><content type="html" xml:base="https://mehmandarov.com/start-docker-containers-automatically/"><![CDATA[<p><em>Starting your Docker containers automatically using <code class="language-plaintext highlighter-rouge">systemd</code>.</em></p>

<ul>
  <li><a href="#introduction">Introduction</a></li>
  <li><a href="#create-the-service-file">Create the Service File</a></li>
  <li><a href="#activate-the-service">Activate the Service</a></li>
</ul>

<hr />

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

<p>After your Docker containers are set up and running, you might need to be able to start some of them automatically on a reboot or a crash. There are several ways of getting this done.</p>

<p>One of them is to use <a href="https://docs.docker.com/engine/admin/start-containers-automatically/" target="_blank">restart policies</a> provided by Docker. They can be set to control whether your containers start automatically when they exit, or when Docker restarts.</p>

<p>Alternatively, you can use a process manager such as <code class="language-plaintext highlighter-rouge">upstart</code>, <code class="language-plaintext highlighter-rouge">systemd</code>, or <code class="language-plaintext highlighter-rouge">supervisor</code> instead. In this post, I want to show you how it is done with <a href="https://freedesktop.org/wiki/Software/systemd/" target="_blank"><code class="language-plaintext highlighter-rouge">systemd</code></a>.</p>

<h2 id="create-the-service-file">Create the Service File</h2>

<p>To create a service file that will be used by <code class="language-plaintext highlighter-rouge">systemd</code> (<code class="language-plaintext highlighter-rouge">systemctl</code> command), we will first need to get your container name. This can be done by running the following command in your shell:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span>docker ps <span class="nt">-a</span></code></pre></figure>

<p>The output will look something like this. Select the right container from the list, and note its name in the last column. In this example, we will be using <code class="language-plaintext highlighter-rouge">mywiki</code> container.</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                    PORTS                NAMES
573193cf1d5e        hypriot/rpi-busybox-httpd   "/bin/busybox http..."   2 days ago          Exited (0) 5 hours ago                         mytest
e85753d57a67        easypi/dokuwiki-arm         "/bin/sh -c 'php-f..."   1 days ago          Up 23 hours               0.0.0.0:80-&gt;80/tcp   mywiki</code></pre></figure>

<p>Now, we will need to create a file (choose an appropriate file name for the service):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>nano /etc/systemd/system/docker-dokuwiki.service</code></pre></figure>

<p>Paste the following into the file. Set a proper <code class="language-plaintext highlighter-rouge">Description</code>, and make sure to update the container name in <code class="language-plaintext highlighter-rouge">ExecStart</code> and <code class="language-plaintext highlighter-rouge">ExecStop</code>:</p>

<figure class="highlight"><pre><code class="language-yml" data-lang="yml"><span class="pi">[</span><span class="nv">Unit</span><span class="pi">]</span>
<span class="s">Description=DokuWiki Container</span>
<span class="s">Requires=docker.service</span>
<span class="s">After=docker.service</span>

<span class="pi">[</span><span class="nv">Service</span><span class="pi">]</span>
<span class="s">Restart=always</span>
<span class="s">ExecStart=/usr/bin/docker start -a mywiki</span>
<span class="s">ExecStop=/usr/bin/docker stop -t 2 mywiki</span>

<span class="pi">[</span><span class="nv">Install</span><span class="pi">]</span>
<span class="s">WantedBy=local.target</span></code></pre></figure>

<p>A couple of notes about the script above:</p>
<ol>
  <li>This file is called a <a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html" target="_blank">unit file</a> for <code class="language-plaintext highlighter-rouge">systemd</code>.</li>
  <li>Make sure you don&#8217;t have any extra line brakes within the sections, like <code class="language-plaintext highlighter-rouge">Unit</code>, or <code class="language-plaintext highlighter-rouge">Service</code>.</li>
  <li>The <code class="language-plaintext highlighter-rouge">-a</code> option in the Docker command for <code class="language-plaintext highlighter-rouge">ExecStart</code> makes sure it is running in attached mode, i.e., attaching STDOUT/STDERR and forwarding signals.</li>
  <li>The <code class="language-plaintext highlighter-rouge">-t</code> option in the Docker command for <code class="language-plaintext highlighter-rouge">ExecStop</code> specifies seconds to wait for it to stop before killing the container.</li>
</ol>

<h2 id="activate-the-service">Activate the Service</h2>

<p>Before we can activate the service we have created, we need to reload the unit file. You will also need to run this command anytime you do any modifications to the unit files:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl daemon-reload</code></pre></figure>

<p>To activate the service run the following commands (<em>remember to change the service name</em>):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl start docker-dokuwiki.service
<span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl <span class="nb">enable </span>docker-dokuwiki.service</code></pre></figure>

<p>To disable the service run the following commands (<em>remember to change the service name</em>):</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl stop docker-dokuwiki.service
<span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>systemctl disable docker-dokuwiki.service</code></pre></figure>

<p>Changes will come to effect on a reboot:</p>

<figure class="highlight"><pre><code class="language-shell_session" data-lang="shell_session"><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>reboot</code></pre></figure>

<p>Now you should have a container that will start on a server reboot, Docker restart, or a crash. <em>Congratulations!</em></p>

<p>As a next step, you might want to look at (external documentation links):</p>

<ul>
  <li>Adding some more parameters to the <a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html" target="_blank">unit file</a>.</li>
  <li>Available <a href="https://docs.docker.com/engine/reference/commandline/start/" target="_blank"><code class="language-plaintext highlighter-rouge">docker start</code></a> options.</li>
  <li>Available <a href="https://docs.docker.com/engine/reference/commandline/start/" target="_blank"><code class="language-plaintext highlighter-rouge">docker start</code></a> options.</li>
</ul>

<hr />]]></content><author><name>Rustam Mehmandarov</name></author><summary type="html">Starting your Docker containers automatically using systemd.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://mehmandarov.com/assets/images/posts-images/whale_small.jpeg"/><category term="blog"/><category term="java"/><category term="docker"/><category term="field notes"/><category term="english"/></entry></feed>
