Implementing Docker Containers with Non-Root User Access

La mise en œuvre de conteneurs Docker avec un accès utilisateur non-root renforce la sécurité en minimisant la surface d'attaque. Cette pratique implique de configurer les Dockerfiles et les points d'entrée pour garantir des permissions appropriées.
Table of Contents
mise-en-œuvre-de-conteneurs-docker-avec-un-accès-utilisateur-non-root-2

Running Docker Containers as Non-Root Users

Docker has revolutionized the way we build, manage, and deploy applications. However, running containers as the root user can pose significant security risks. In this article, we’ll explore the importance of running Docker containers as non-root users, the steps required to set it up, and some best practices to ensure your applications are secure.

Comprendre Docker et les permissions utilisateur

Qu'est-ce que Docker ?

Docker est une plateforme open-source qui automatise le déploiement d'applications dans des conteneurs légers. Ces conteneurs encapsulent tout ce qui est nécessaire pour exécuter l'application, y compris le code, le runtime, les outils système, les bibliothèques et les paramètres.

Why Use Non-Root Users?

Lorsqu'un conteneur Docker s'exécute en tant qu'utilisateur root, il possède les mêmes permissions et privilèges que l'utilisateur root sur la machine hôte. Si une vulnérabilité est exploitée au sein du conteneur, un attaquant pourrait obtenir un accès root au système hôte, entraînant de graves implications en matière de sécurité. En exécutant les conteneurs en tant qu'utilisateurs non-root, nous limitons l'étendue des dommages potentiels, rendant plus difficile pour les attaquants de compromettre le système hôte.

Configuration d'un utilisateur non-root dans des conteneurs Docker

Étape 1 : Créer un utilisateur non-root dans le Dockerfile

The first step in running your container as a non-root user is to create a user in your Dockerfile. Below is an example of how to do this while building a simple Node.js application.

# Start with a base image
FROM node:14

# Create a non-root user
RUN groupadd -g 1001 appuser && 
    useradd -u 1001 -g appuser -m appuser

# Set the working directory
WORKDIR /home/appuser/app

# Copy package.json and install dependencies
COPY package.json ./
RUN npm install

# Copy the rest of your application code
COPY . .

# Switch to the non-root user
USER appuser

# Start the application
CMD ["node", "app.js"]

Dans le Dockerfile ci-dessus :

  • Nous créons un utilisateur non-root. appuser et un groupe appuser with specific IDs.
  • Nous définissons le répertoire de travail sur un chemin à l'intérieur du appuser’s home directory.
  • Finally, we switch to the appuser before running the application.

Étape 2 : Créer l'image Docker

Après avoir créé votre Dockerfile, vous pouvez construire votre image en utilisant l'interface de ligne de commande Docker :

docker build -t mon-application-node .

Étape 3 : Exécution du conteneur Docker

Une fois l'image construite, vous pouvez l'exécuter et elle s'exécutera en tant qu'utilisateur non-root spécifié dans le Dockerfile.

docker run -d mon-application-node

Vérification de l'exécution non-root

Pour vérifier que votre conteneur s'exécute en tant qu'utilisateur non-root, vous pouvez exécuter une commande à l'intérieur du conteneur :

docker exec -it  whoami

The output should return appuser, confirmant que l'application s'exécute en tant qu'utilisateur non-root.

Bonnes pratiques pour exécuter des conteneurs Docker en tant qu'utilisateurs non-root

1. Spécifier les identifiants utilisateur et groupe

When creating a non-root user, always specify both user and group IDs. This practice helps avoid conflicts with existing users and groups on the host system. Using 1001 as shown in the earlier example is common, but ensure you check for existing IDs that may cause overlaps.

2. Use Read-Only Filesystems

Exécuter des conteneurs avec des systèmes de fichiers en lecture seule renforce la sécurité. Vous pouvez y parvenir en spécifiant le lecture seule option when running your container.

docker run --read-only -d my-node-app

Cela restreint les écritures à des répertoires spécifiques si nécessaire (comme /tmp ou volumes montés).

3. Limit Container Capabilities

By default, containers run with a set of capabilities that can be excessive for many applications. You can drop unnecessary capabilities to further minimize security risks.

docker run --cap-drop ALL -d mon-app-node

Then, explicitly add any capabilities your application needs, like NET_BIND_SERVICE for binding to lower ports.

4. Use Docker’s User Namespace

Docker offre une fonctionnalité appelée espaces de noms d'utilisateurs qui vous permet de remapper les identifiants d'utilisateur et de groupe dans le conteneur vers des identifiants différents sur l'hôte. Cela ajoute une couche de sécurité supplémentaire en garantissant que même si un attaquant parvient à accéder au conteneur, il est toujours limité par les identifiants remappés.

To enable user namespaces, you need to modify the Docker daemon configuration. On Linux, this is typically done in /etc/docker/daemon.json. Add the following configuration:

{
  "userns-remap": "par défaut"
}

5. Mettez régulièrement à jour les images

Keeping your base images updated is crucial for security. Make it a habit to regularly pull the latest versions of your base images and rebuild your containers.

docker pull node:14
docker build -t my-node-app .

6. Use Docker Compose for Development

L'utilisation de Docker Compose peut simplifier la gestion de plusieurs services. Vous pouvez définir les paramètres utilisateur dans votre docker-compose.yml file to ensure your containers run as non-root users:

version: '3'
services:
  app:
    build: .
    user: appuser
    read_only: true

7. Surveiller et auditer les conteneurs

Implementing monitoring and auditing solutions can help in detecting issues in your containers. Tools such as Prometheus, Grafana, or more specialized container security tools can assist in monitoring resource usage, log management, and compliance checks.

Défis de l'exécution de conteneurs en tant qu'utilisateurs non-root

Bien que l'exécution de conteneurs Docker en tant qu'utilisateurs non-root améliore la sécurité, vous pouvez rencontrer certains défis :

1. Problèmes de permissions

Si votre application tente d'écrire dans des répertoires ou des fichiers pour lesquels l'utilisateur non-root n'a pas les permissions nécessaires, vous rencontrerez des erreurs de permission.

Pour résoudre ce problème, assurez-vous que tous les répertoires auxquels votre application doit écrire disposent des permissions appropriées, définies dans le Dockerfile ou au moment de l'exécution.

2. Compatibilité avec les applications existantes

Some applications may not be designed with non-root execution in mind. You may need to refactor certain aspects of your applications to work correctly under a non-root user.

3. Limited Capabilities

L'exécution en tant qu'utilisateur non-root limite certaines opérations, telles que la liaison à des ports privilégiés (ports inférieurs à 1024). Vous devrez peut-être ajuster votre application ou utiliser un proxy inverse pour acheminer le trafic de manière appropriée.

Conclusion

L'exécution des conteneurs Docker en tant qu'utilisateurs non-root est une pratique essentielle qui améliore la sécurité de vos déploiements d'applications. En créant un utilisateur dédié dans votre Dockerfile, en suivant les meilleures pratiques telles que l'utilisation de systèmes de fichiers en lecture seule, la limitation des capacités et l'utilisation des espaces de noms d'utilisateurs, vous pouvez réduire considérablement la surface d'attaque de vos conteneurs.

Bien qu'il puisse y avoir des défis lors de la transition des applications existantes pour qu'elles s'exécutent en tant qu'utilisateurs non-racine, les avantages l'emportent largement sur les risques associés à l'exécution des conteneurs en tant que root. En mettant en œuvre les stratégies abordées dans cet article, vous adoptez une approche proactive pour sécuriser vos applications Dockerisées.

Ressources supplémentaires

By understanding and applying these principles, you can ensure that your Docker containers operate securely and efficiently while minimizing risks.