<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Containers on Sysadmin Tales</title>
    <link>https://blog.ssb-tech.net/tags/containers/</link>
    <description>Recent content in Containers on Sysadmin Tales</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 02 Oct 2026 21:39:10 -0400</lastBuildDate>
    <atom:link href="https://blog.ssb-tech.net/tags/containers/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Getting started with Docker</title>
      <link>https://blog.ssb-tech.net/posts/docker-pitfalls/</link>
      <pubDate>Sun, 26 Oct 2025 15:41:37 -0400</pubDate>
      <guid>https://blog.ssb-tech.net/posts/docker-pitfalls/</guid>
      <description>&lt;h1 id=&#34;getting-started-with-docker&#34;&gt;Getting started with Docker&lt;/h1&gt;&#xA;&lt;p&gt;&lt;em&gt;So, you wanna use docker-compose&amp;hellip;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;Welcome! If you&amp;rsquo;re looking at this post, I assume that you&amp;rsquo;re new to Docker and you want to learn to get up and running quickly.&lt;/p&gt;&#xA;&lt;p&gt;There are several areas of Docker that confuse new users, and I will do my best to address most of the most common pitfalls in this post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker-run-vs-docker-compose&#34;&gt;docker run vs docker compose&lt;/h2&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t use &lt;code&gt;docker run&lt;/code&gt;. If the thing you want to run in Docker only gives you the &lt;code&gt;docker run&lt;/code&gt; syntax, you take that thing over to &lt;a href=&#34;https://www.composerize.com/&#34;&gt;Composerize&lt;/a&gt; and you convert it.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s nothing particularly &lt;em&gt;wrong&lt;/em&gt; with &lt;code&gt;docker run&lt;/code&gt;, but &lt;code&gt;docker compose&lt;/code&gt; is far easier to maintain and troubleshoot.&lt;/p&gt;&#xA;&lt;p&gt;Tools like &lt;a href=&#34;https://github.com/adrienverge/yamllint&#34;&gt;yamllint&lt;/a&gt; make diagnosing issues with compose file formatting much more tractable.&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker-networking&#34;&gt;Docker networking&lt;/h2&gt;&#xA;&lt;p&gt;This seems to be the area that causes the most confusion.&lt;/p&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t worry, you don&amp;rsquo;t need to be a network engineer to get a grasp of this, but having a good understanding of how networking works is very helpful.&lt;/p&gt;&#xA;&lt;h3 id=&#34;network-namespaces&#34;&gt;Network namespaces&lt;/h3&gt;&#xA;&lt;p&gt;Docker uses Linux kernel &lt;a href=&#34;https://blog.scottlowe.org/2013/09/04/introducing-linux-network-namespaces/&#34;&gt;network namespaces&lt;/a&gt; to achieve isolation. You don&amp;rsquo;t need to really understand any of this, but click the link if you&amp;rsquo;re at all interested.&lt;/p&gt;&#xA;&lt;p&gt;Effectively what this means is that containers by default are isolated from both the host operating system&amp;rsquo;s networking stack, and from each other.&lt;/p&gt;&#xA;&lt;p&gt;Whenever you create a new Docker compose project, by default it will create a new Docker network bridge, with its own internal subnet and DNS.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Containers in the same Docker compose project (in the same docker-compose.yml file, or separate files linked together with the &lt;code&gt;-p&lt;/code&gt; flag) share the same network bridge, and thereby are able to communicate with each other.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;communicating-with-containers-by-name&#34;&gt;Communicating with containers by name&lt;/h3&gt;&#xA;&lt;p&gt;Docker also does some things under the hood to make it possible for docker containers in the same stack to communicate with each other by service name.&lt;/p&gt;&#xA;&lt;p&gt;To illustrate this, lets go with a simple example.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;POSTGRES_CONNECTION_STRING=postgresql://postgres-db1:5432&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./config:/config&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;postgres-db1&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Above, we have an extremely simple docker compose file, with a single application and a PostgreSQL database.&lt;/p&gt;&#xA;&lt;p&gt;You can see in the &lt;code&gt;POSTGRES_CONNECTION_STRING&lt;/code&gt; environment variable that it is using the name of the service to communicate with the database.&lt;/p&gt;&#xA;&lt;h3 id=&#34;creating-network-bridges&#34;&gt;Creating network bridges&lt;/h3&gt;&#xA;&lt;p&gt;But what if I don&amp;rsquo;t want or can&amp;rsquo;t have the containers in the same Compose project?&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s where creating your own bridges comes in.&lt;/p&gt;&#xA;&lt;p&gt;There are several different adapter types in Docker, the most common of them is the bridge, so that&amp;rsquo;s the only one we&amp;rsquo;ll be talking about in this article.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m sure as hell not going to get into macvlan or any of that, that&amp;rsquo;s a whole article on its own.&lt;/p&gt;&#xA;&lt;p&gt;Here you can create a bridge:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;docker network create proxy&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Where &lt;code&gt;proxy&lt;/code&gt; can be anything you like, it&amp;rsquo;s just the name you gave the bridge.&lt;/p&gt;&#xA;&lt;p&gt;This is how you can use external bridges in Docker compose:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;app01&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;proxy&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;proxy&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;external&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The key here is that you specify that the network is &lt;em&gt;external&lt;/em&gt; to the compose project, and that you specify that each container should use that network instead of the default bridge that would have been created.&lt;/p&gt;&#xA;&lt;p&gt;You can also specify more than one network per container. This can be useful if you have some containers that need external connectivity but others that don&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;p&gt;For example, you could have one bridge that&amp;rsquo;s used by containers to communicate with the database, and another that the frontend uses to talk to the backend.&lt;/p&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;app01&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;proxy&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;database&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;proxy&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;external&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;database&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the &lt;code&gt;database&lt;/code&gt; network is &lt;em&gt;not&lt;/em&gt; external here, so it will be created when you run &lt;code&gt;docker compose up&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;exposing-ports&#34;&gt;Exposing ports&lt;/h3&gt;&#xA;&lt;p&gt;Next, lets get into how Docker handles exposing ports.&lt;/p&gt;&#xA;&lt;p&gt;Lets take the Jellyfin docker compose file for an example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;jellyfin&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;lscr.io/linuxserver/jellyfin:latest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;jellyfin&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;PUID=1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;PGID=1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;TZ=Etc/UTC&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;JELLYFIN_PublishedServerUrl=http://192.168.0.5&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/path/to/jellyfin/library:/config&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/path/to/tvseries:/data/tvshows&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/path/to/movies:/data/movies&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;8096&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;8096&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;8920&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;8920&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;7359&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;7359&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;/udp&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;1900&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;1900&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;/udp&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;ll notice the &lt;code&gt;ports&lt;/code&gt; key. These are what&amp;rsquo;s known as &lt;a href=&#34;https://docs.docker.com/get-started/docker-concepts/running-containers/publishing-ports/&#34;&gt;published ports&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The number on the left is what is mapped &lt;em&gt;outside&lt;/em&gt; the container (on the machine running Docker), and the one on the right is inside the container.&lt;/p&gt;&#xA;&lt;p&gt;In 99% of cases, you want to leave the number on the right alone.&lt;/p&gt;&#xA;&lt;p&gt;For example, if I wanted the Jellyfin web interface, which by default runs on port 8096, and expose it on port 9001, I could change the compose file like so:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;9001&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;8096&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;8920&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;8920&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;7359&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;7359&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;/udp&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;1900&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;1900&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;/udp&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;#optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, on to another example.&lt;/p&gt;&#xA;&lt;p&gt;In many cases, you may not want to expose any ports at all!&lt;/p&gt;&#xA;&lt;p&gt;If users external to the Docker host don&amp;rsquo;t need to be able to touch that port, then simply don&amp;rsquo;t publish it.&lt;/p&gt;&#xA;&lt;p&gt;Take this other example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;proxy&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jc21/nginx-proxy-manager:latest&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;80:80&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# Public HTTP Port&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;443:443&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# Public HTTPS Port&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;81:81&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# Admin Web Port&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Add any other Stream port you want to expose&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# - &amp;#39;21:21&amp;#39; # FTP&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./data:/data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;vaultwarden&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;vaultwarden/server:latest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;vaultwarden&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DOMAIN&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://vw.domain.tld&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./vw-data/:/data/&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;ll notice that the &lt;a href=&#34;https://github.com/dani-garcia/vaultwarden&#34;&gt;Vaultwarden&lt;/a&gt; container doesn&amp;rsquo;t have any published ports.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s because it doesn&amp;rsquo;t need them. In this scenario, we would go into &lt;a href=&#34;https://nginxproxymanager.com/&#34;&gt;Nginx Proxy Manager&lt;/a&gt; and configure a proxy host for it.&lt;/p&gt;&#xA;&lt;p&gt;All communication with Vaultwarden would go through the proxy, so there&amp;rsquo;s no need to expose the port.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Remember that when containers are talking internally like this, you use the INTERNAL port (the one that would be on the right), instead of the one you would have exposed on the outside.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Nginx can talk to Vaultwarden and vice versa - there is no reason for a user to directly interact with the other container, so why let them?&lt;/p&gt;&#xA;&lt;p&gt;This is also valid syntax:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;127.0.0.1&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;8000&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is telling the container to only publish port 8000 on &lt;code&gt;localhost&lt;/code&gt;. You can substitute any other IP here to make it only listen on that one interface.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t use this a whole lot.&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker-volumes&#34;&gt;Docker volumes&lt;/h2&gt;&#xA;&lt;p&gt;Docker volumes are simply a piece of your filesystem that you&amp;rsquo;re giving to the container to store persistent data.&lt;/p&gt;&#xA;&lt;p&gt;By definition, Docker containers are &lt;a href=&#34;https://www.merriam-webster.com/dictionary/ephemeral&#34;&gt;ephemeral.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Unless you configure a volume, any data produced while the container is running will be lost when the container is destroyed.&lt;/p&gt;&#xA;&lt;p&gt;The two most popular ways to configure volumes in Docker are named Docker volumes and bind mounts.&lt;/p&gt;&#xA;&lt;p&gt;This is a named docker volume:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres-data:/var/lib/postgresql/data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this is a bind mount:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;/apps/myapp/postgres-data:/var/lib/postgresql/data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;callout callout-note&#34; role=&#34;note&#34;&gt;&lt;div class=&#34;callout-title&#34;&gt;Note&lt;/div&gt;&lt;div class=&#34;callout-content&#34;&gt;&lt;p&gt;If it&amp;rsquo;s a filesystem path on the left, it&amp;rsquo;s a bind mount.&lt;/p&gt;&#xA;&lt;p&gt;The path on the right is the &lt;a href=&#34;https://askubuntu.com/questions/83518/what-are-mountpoints-and-which-one-should-i-pick&#34;&gt;mountpoint&lt;/a&gt; inside the container.&lt;/p&gt;&#xA;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Honestly as far as I&amp;rsquo;m concerned it&amp;rsquo;s mostly personal preference which you use. I like using bind mounts as it makes it easier to keep track of where your data is.&lt;/p&gt;&#xA;&lt;p&gt;Named docker volumes will store the data in a subdirectory under &lt;code&gt;/var/lib/docker/volumes/&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Whichever one you use, please make sure you do backups&amp;hellip; I&amp;rsquo;m not going to help you try and get your data back, sorry.&lt;/p&gt;&#xA;</description>
    </item>
  </channel>
</rss>
