<?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>Forem: izackv</title>
    <description>The latest articles on Forem by izackv (@izackv).</description>
    <link>https://forem.com/izackv</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%2F1054898%2F077c4eee-679c-42e1-bdf7-1b769e755ea3.jpg</url>
      <title>Forem: izackv</title>
      <link>https://forem.com/izackv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/izackv"/>
    <language>en</language>
    <item>
      <title>Running a Docker Container with a Custom Non-Root User: Syncing Host and Container Permissions</title>
      <dc:creator>izackv</dc:creator>
      <pubDate>Wed, 29 Mar 2023 19:52:02 +0000</pubDate>
      <link>https://forem.com/izackv/running-a-docker-container-with-a-custom-non-root-user-syncing-host-and-container-permissions-26mb</link>
      <guid>https://forem.com/izackv/running-a-docker-container-with-a-custom-non-root-user-syncing-host-and-container-permissions-26mb</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvhic3eq1tzpxdigvtax.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvhic3eq1tzpxdigvtax.jpg" alt="Containers" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Docker has become a popular platform for developers to create, deploy, and run applications in a portable, consistent environment.  &lt;/p&gt;

&lt;p&gt;By default, Docker containers run as the root user, which can pose security risks if the container becomes compromised. &lt;br&gt;
Also, running as root can be an issue when sharing folders between the host and the docker container.  &lt;/p&gt;

&lt;p&gt;To reduce these risks, we'll discuss running a Docker container with a custom non-root user that matches your host Linux user's user ID (&lt;code&gt;UID&lt;/code&gt;) and group ID (&lt;code&gt;GID&lt;/code&gt;), ensuring seamless permission handling for mounted folders.&lt;/p&gt;

&lt;p&gt;Running a docker build command that uses (mainly) a non-root user might force us to use &lt;code&gt;sudo&lt;/code&gt; for some commands.&lt;br&gt;
The same is valid for running the docker itself using unattended scripts.&lt;br&gt;
You may need elevated privileges for specific tasks. &lt;br&gt;
Granting password-less sudo permissions to a non-root user allows you to perform administrative tasks without the risk of running the entire container as the root user.&lt;/p&gt;

&lt;p&gt;Here are the steps to create and run a Docker container with a non-root user and password-less sudo permissions:&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Adjust the Dockerfile to Accept UID and GID as Arguments
&lt;/h2&gt;

&lt;p&gt;Modify your Dockerfile to accept the host's UID and GID as arguments. This way, you can create a user in the container with a matching UID and GID.&lt;br&gt;
Add the following lines to your Dockerfile:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; UID&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; GID&lt;/span&gt;

&lt;span class="c"&gt;# Update the package list, install sudo, create a non-root user, and grant password-less sudo permissions&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    addgroup &lt;span class="nt"&gt;--gid&lt;/span&gt; &lt;span class="nv"&gt;$GID&lt;/span&gt; nonroot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    adduser &lt;span class="nt"&gt;--uid&lt;/span&gt; &lt;span class="nv"&gt;$UID&lt;/span&gt; &lt;span class="nt"&gt;--gid&lt;/span&gt; &lt;span class="nv"&gt;$GID&lt;/span&gt; &lt;span class="nt"&gt;--disabled-password&lt;/span&gt; &lt;span class="nt"&gt;--gecos&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; nonroot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'nonroot ALL=(ALL) NOPASSWD: ALL'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/sudoers

&lt;span class="c"&gt;# Set the non-root user as the default user&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; nonroot&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 2: Set the Working Directory
&lt;/h2&gt;

&lt;p&gt;Set the working directory where the non-root user can access it. Add the following line to your Dockerfile:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="c"&gt;# Set the working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/nonroot/app&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This sets the working directory to '/home/nonroot/app', where the non-root user has read and write permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Copy Files and Set Permissions
&lt;/h2&gt;

&lt;p&gt;Ensure the non-root user has the necessary permissions to access the copied files. Add the following lines to your Dockerfile:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="c"&gt;# Copy files into the container and set the appropriate permissions&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=nonroot:nonroot . /home/nonroot/app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 755 /home/nonroot/app


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 4: Build and Run the Docker Container with UID and GID Parameters
&lt;/h2&gt;

&lt;p&gt;Now you can build the Docker image and run the container with the custom non-root user. Pass your host's UID and GID as build arguments to create a user with matching permissions.&lt;br&gt;
Use the following commands to build and run your container:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# Get your host's UID and GID&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HOST_UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HOST_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Build the Docker image&lt;/span&gt;
docker build &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOST_UID&lt;/span&gt; &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOST_GID&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; your-image-name &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Run the Docker container&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; your-container-name your-image-name &lt;span class="nb"&gt;id&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The docker output will be:&lt;br&gt;
&lt;code&gt;uid=1000(nonroot) gid=1000(nonroot) groups=1000(nonroot)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional - Adding Docker Compose for Running a Custom Non-Root User Container
&lt;/h2&gt;

&lt;p&gt;Docker Compose is a tool for defining and running multi-container applications using a YAML file to configure the application's services, networks, and volumes. &lt;br&gt;
It simplifies managing containers, especially when working with multiple services. &lt;br&gt;
This section will discuss how to use Docker Compose to run a Docker container with a custom non-root user that matches your host's UID and GID.&lt;br&gt;
Create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file in your project directory with the following content:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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.8'&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;your_service_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;UID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${HOST_UID}&lt;/span&gt;
        &lt;span class="na"&gt;GID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${HOST_GID}&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;your-image-name&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-container-name&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./app:/home/nonroot/app&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This YAML file defines a service, &lt;code&gt;your_service_name&lt;/code&gt;, using the Dockerfile in the current directory. The &lt;code&gt;build&lt;/code&gt; section passes the &lt;code&gt;UID&lt;/code&gt; and &lt;code&gt;GID&lt;/code&gt; build arguments from the host environment variables &lt;code&gt;HOST_UID&lt;/code&gt; and &lt;code&gt;HOST_GID&lt;/code&gt;. The &lt;code&gt;volumes&lt;/code&gt; section maps a local directory (&lt;code&gt;./app&lt;/code&gt;) to the container's working directory (&lt;code&gt;/home/nonroot/app&lt;/code&gt;), ensuring seamless permission handling for the mounted folder.&lt;/p&gt;

&lt;p&gt;First, to run the container using Docker Compose set the &lt;code&gt;HOST_UID&lt;/code&gt; and &lt;code&gt;HOST_GID&lt;/code&gt; environment variables in your host system.&lt;br&gt;
The following command will build the docker (if needed), start it, print the user ID, and remove the container:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="nv"&gt;HOST_UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;HOST_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; docker compose run &lt;span class="nt"&gt;--rm&lt;/span&gt; your_service_name &lt;span class="nb"&gt;id&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Running a Docker container with a custom non-root user that matches your host's UID and GID ensures seamless permission handling for mounted folders while maintaining security. &lt;br&gt;
Optimizing the Dockerfile and combining RUN commands can reduce the image size and improve performance. Following these steps will help you create and run a Docker container with a non-root user that aligns with your host's permissions, reducing the risk of potential security breaches and permission issues. Always prioritize security when deploying applications and containers to ensure a safe and stable environment.&lt;/p&gt;

&lt;p&gt;Integrating Docker Compose into your workflow simplifies container management and improves the overall development experience, allowing you to focus on building your application. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>security</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
