
            
        
        
            
        
            
        
        
            
        
            
        
        
            
        
        
        
        
        
        
        
        
        
        
        
            
        
        
            
        
            
        
        
            
        
            
        
        
            
        
        [{"categories":[{"LinkTitle":"DevOps","RelPermalink":"/categories/devops/"}],"content":"Goals Configure a fully functional dockerized Jenkins setup for both the Controller (Master) and an Agent (Slave) Route the config through our previously set Traefik reverse proxy Introduction Before proceeding to the core of our setup, let\u0026rsquo;s introduce a few key concepts.\nModern CI/CD pipelines face a common challenge: creating a consistent, clean, and reproducible build environment.\nTraditional methods often lead to dependency conflicts and \u0026ldquo;works on my machine\u0026rdquo; issues.\nDocker provides the perfect solution by packaging applications and their dependencies into isolated containers. When we combine Jenkins, the leading automation server, with Docker, we create a powerful and flexible CI/CD system.\nThis integration can be set up in two primary ways:\nJenkins inside a Docker container that also has a Docker daemon (Docker-in-Docker or DinD).\nJenkins inside a Docker container that uses the host\u0026rsquo;s Docker daemon (Docker-out-of-Docker or DoD).\nThe following is a quick comparison of Dind and DoD in regards to Jenkins: Feature Docker-in-Docker (DinD) Docker-out-of-Docker (DoD) How It Works Jenkins container runs its own, nested Docker daemon. Jenkins container uses the host\u0026rsquo;s Docker daemon. Security ⚠️ Know what you\u0026rsquo;re doing! Requires the --privileged flag. ✅ Strait forward. No privileged mode needed. Performance 🔻 Poor. Overhead from multiple daemons; no shared cache. ✅ Excellent. Single daemon, and shared image cache. Isolation ✅ Full. Each build is isolated from the host and other jobs. 🔻 Limited. All containers are \u0026ldquo;siblings\u0026rdquo; on the same host. Important! This article will be covering exclusively the DoD approach. And, to keep everything simple, I will be using the same host for both the Controller and the Agent.\nSource code Here you\u0026rsquo;ll find the source code for a fully functional Jenkins install:\nController (master) : https://github.com/a-naitslimane/anaitslimane.article.jenkins-traefik-docker.jenkins-controller Agent (slave) : https://github.com/a-naitslimane/anaitslimane.article.jenkins-traefik-docker.jenkins-agent Setup Prerequisites: Docker and Docker Compose installed on your machine A Dockerized Traefik reverse proxy running locally. If not, please follow through my previous article Traefik reverse proxy Important! The following configs are strongly linked to my previous article\u0026rsquo;s configs. Please remember to adjust with your own values. Especially the external docker network\u0026rsquo;s name\nContainer setup Clone the source code to a working-directory\nSet environment variables\nCreate a copy of .env.exemple named .env. In it, you can set your own values of course, as long as they are consistent with the rest of the following config.\nBind your DOMAIN_NAME to the localhost:\nAdd your local domain name to the hosts file: C:\\Windows\\System32\\drivers\\etc\\hosts (on Windows) and /etc/hosts (on Linux).\n127.0.0.1 ci-cd-ctrl.my-local-domain.com\rLaunch the service using docker compose:\nIn your terminal, first cd to your working-directory then type: docker compose up\rTesting the Controller Check that the controller\u0026rsquo;s container is running and healthy. Grab the password set by default. In your browser, open the address you\u0026rsquo;ve configured as DOMAIN_NAME (ex: ci-cd-ctrl.my-local-domain.com)\nEnter the password you\u0026rsquo;ve picked in the previous instruction Click on your preferred way of plugin installation. Note that you can manage plugins later. Fill-in your admin profile account Set up the Jenkins URL with the value of your DOMAIN_NAME (ex: ci-cd-ctrl.my-local-domain.com) What about the Agent (Node) ? There are two methods to link the agent to controller provided in the Launch method. The first requires to connect the agent to the controller in which case the controller\u0026rsquo;s inbound port needs to be set and configured. Please refer in this case to the jenkins/ssh-agent docs For this article, I specifically chose the second option! Which goes the other way around. Meaning that the controller has to connect to the agent, via SSH.\nIn order to achieve that, we . Then we need to create what is called in jenkins: credentials. Please refer to the jenkins docs to learn more about how to manage credentials Here again, we\u0026rsquo;ll be given multiple options, and I chose a specific one which is \u0026ldquo;SSH Username with private key\u0026rdquo;. It requires the creation of a SSH key pair to use between the controller/agent.\nNow that the full context is set, let\u0026rsquo;s go through the process:\nPreparing the SSH configuration connect into the controller container\u0026rsquo;s console (bash is available in the image):\ndocker exec -it ci-cd-jenkins-ctrl bash\rGenerate the key (here I chose the ssh-ed25519 algorithm but it could be any) with the following command. Leave the passphrase blank in order to avoid unnecessary headache for now.\nssh-keygen -t ed25519 -C \u0026#34;jenkins\u0026#34;\rThis will generate the SSH key pair (private/public) that we will use next in our credentials configuration. The default directory in which the keys (private/public) will be saved should be \u0026rsquo;/var/jenkins_home/.ssh\u0026rsquo;\nAdding the credentials Go to the controller\u0026rsquo;s dashboard\nClick on Manage Jenkins \u0026gt; Credentials\nYou can create a domain for which these credentials apply specifically Or, as I did for simplicity, just chose the default Global credentials (unrestricted)\nClick on adding some credentials\nAs stated in the context above, we choose the SSH Username with private key option\nEnter jenkins in the Username field (the user associated with the SSH key)\nIn the Private Key, select Enter directly Click Add, copy and paste the full private SSH key created previously for the user jenkins\nAdding the Agent (Node) Go to the controller\u0026rsquo;s dashboard\nOn the left menu, click on the Build executor Status link Click on New Node to start adding our agent On the next screen, give it a name, select Permanent Agent, and click Create\nNext, fill-in the required fields, especially :\n\u0026ldquo;Launch method\u0026rdquo; which should be Launch agent via SSH \u0026ldquo;Host\u0026rdquo; should be the name of the agent container ci-cd-jenkins-ssh-agent \u0026ldquo;Remote root directory\u0026rdquo; which should be /home/jenkins/agent Select the credentials created previously (with the username jenkins) Select the \u0026ldquo;Host Key Verification Strategy\u0026rdquo;, I chose the Manually trusted key Verification Strategy Now everything is set and ready for our next step!\nLaunching the agent\u0026rsquo;s docker container Clone the source code to a working-directory\nSet environment variables\nCreate a copy of .env.exemple named .env. In it, you can set your own values of course, as long as they are consistent with the rest of the following config.\nIn particular, set the SSH_PUBKEY value. It is the public ssh key you\u0026rsquo;ve generated previously in the controller ## env ##\r1 PORT_JENKINS_AGENT_SSH=22 2 COMPOSE_PROJECT_NAME=ci-cd-jenkins-ssh-agent 3 DOCKER_GROUP_ID=0 4 SSH_PUBKEY=\u0026lt;your own full public key here\u0026gt;\rlaunch the agent\nIn your terminal, cd to your working-directory then type : docker compose up\rTesting the agent Go to the controller\u0026rsquo;s dashboard Select your agent Click on the Launch agent button et voilà ! You\u0026rsquo;re set Common Pitfalls \u0026amp; Troubleshooting Basic Incorrect Public Key: A typing error of the public key will prevent any connection. It is crucial to strictly follow the format expected by the agent container. Fix: Verify that the key begins with its type (e.g., ssh-ed25519) and does not contain any stray line breaks within your .env file. Private Key Formatting: When creating Credentials in Jenkins, adding extra spaces or incorrect line breaks will invalidate the key. Fix: Copy the entire block, including the -----BEGIN... and ...END----- headers, without manually altering the content. SSH Port Configuration: When setting up the Node on the Jenkins dashboard, the connection will fail if the port does not match the one exposed by the agent container. Fix: Ensure the \u0026ldquo;Port\u0026rdquo; field in Jenkins exactly matches the PORT_JENKINS_AGENT_SSH value defined in your Docker configuration (default is 22). Advanced Docker Socket Permissions: This is the most common DoD issue. If the Jenkins user inside the agent container doesn\u0026rsquo;t have permission to access /var/run/docker.sock, your builds will fail with a \u0026ldquo;Permission Denied\u0026rdquo; error. Fix: Ensure the DOCKER_GROUP_ID in your .env matches the GID of the docker group on your host machine. Traefik Timeout during Long Builds: If a build step involves a long-running process that communicates via HTTP (like a large image upload/download), Traefik might drop the connection if idle timeouts are too low. Fix: Check your Traefik entrypoint configuration for respondingTimeouts if you see unexpected 504 Gateway Timeouts. Zombies and Orphan Processes: Since the build containers are \u0026ldquo;siblings\u0026rdquo; to the agent, if an agent container is force-stopped or crashes, it might leave \u0026ldquo;orphan\u0026rdquo; build containers running on the host. Fix: Periodically run docker ps on the host to ensure no rogue build containers are consuming resources after a failed pipeline. MTU Mismatch (Network issues): If you are running this on a Cloud VPS (like OpenStack or AWS), the default MTU (Maximum Transmission Unit) of 1500 might be too high for nested Docker networks, causing apt-get or npm install to hang. Fix: Ensure the Docker network MTU inside your containers matches the host\u0026rsquo;s MTU (usually 1450 or 1400 in virtualized environments). Wrapping Up By routing your Jenkins Controller and Agent through Traefik, you’ve moved beyond a basic lab setup into a professional, reverse-proxied CI/CD environment. The DoD approach ensures your builds remain fast by leveraging the host’s image cache, while the SSH-based Agent configuration keeps your architecture decoupled and secure.\nThe Architect\u0026rsquo;s Final Note:\nScalability: You can now horizontally scale by adding more agents using the same SSH pattern across different hosts. Maintenance: Since build containers are \u0026ldquo;siblings\u0026rdquo; on your host, remember to run docker image prune occasionally to keep your environment clean. You now have a robust, containerized automation stack ready to handle complex pipelines. Happy automating!\n","permalink":"/posts/traefik/jenkins/","tags":[{"LinkTitle":"Jenkins","RelPermalink":"/tags/jenkins/"},{"LinkTitle":"CI/CD","RelPermalink":"/tags/ci/cd/"},{"LinkTitle":"Docker","RelPermalink":"/tags/docker/"},{"LinkTitle":"Docker Compose","RelPermalink":"/tags/docker-compose/"},{"LinkTitle":"Traefik","RelPermalink":"/tags/traefik/"}],"title":"Fully Dockerized *(DoD)* Jenkins setup through Traefik"},{"categories":[{"LinkTitle":"DevOps","RelPermalink":"/categories/devops/"}],"content":"Goals Configure and run the right containers to tunnel requests into a PHP-FPM server through a Nginx webserver, all through our previously set Traefik reverse proxy Introduction The Specificity of PHP-FPM (FastCGI Process Manager) The key is in the architecture\u0026rsquo;s approach to PHP.\nTraditional Method: In a traditional setup (e.g. Apache with mod_php), the web server and the PHP interpreter are a single, monolithic process. Every time a new web request comes in, a new Apache process is created that contains the entire PHP engine. This is simple to set up, but it\u0026rsquo;s resource-intensive and doesn\u0026rsquo;t scale well, especially for large numbers of requests.\nPHP-FPM Method: PHP-FPM separates the concerns. The web server (Nginx) is optimized for what it does best (serving files), and PHP-FPM is a separate, dedicated process pool optimized for running PHP. This allows each component to be highly performant and scalable. When the system is under heavy load, you can simply scale the PHP-FPM service without affecting the web server. This approach is much more efficient and resilient for modern web applications.\nThe Request Flow A request enters Traefik on port 443 (HTTPS), which decrypts it and sends it to Nginx. Nginx, acting as a proxy, forwards the request to PHP-FPM on a private internal network. PHP-FPM processes the code, sends the output back to Nginx, and Nginx returns the final content back to Traefik, which then encrypts and delivers it to the user. As shown in the following diagram.\nOverview of the Docker - Traefik - Nginx - PHP-FPM Request Flow\rSource code Here you\u0026rsquo;ll find the source code for a basic PHP demo page showing how the different containers work together to handle requests: https://github.com/a-naitslimane/anaitslimane.article.php-fpm-traefik-docker Setup Prerequisites: Docker and Docker Compose installed on your machine A Dockerized Traefik reverse proxy running locally. If not, please follow through my previous article Traefik reverse proxy Important! The following configs are strongly linked to my previous article\u0026rsquo;s configs. Please remember to adjust with your own values. Especially the external docker network\u0026rsquo;s name\nLocal setup Clone the source code to your working-directory\nSet environment variables\nCreate a copy of .env.exemple named .env. In it, you can set your own values of course, as long as they are consistent with the rest of the following config.\\\nBind your DOMAIN_NAME to the localhost:\nAdd your local domain name to the hosts file: C:\\Windows\\System32\\drivers\\etc\\hosts (on Windows) and /etc/hosts (on Linux).\n127.0.0.1 php-fpm.demo.domain\rLaunch the services using docker compose:\nIn your terminal, first cd to your working-directory then type: docker compose -f docker-compose.yaml -f up\rTesting Check that both the nginx and php-fpm containers are running and healthy.\nIn your browser, open the address you\u0026rsquo;ve configured as DOMAIN_NAME (ex: https://php-fpm.demo.domain )\nYou should be seeing the following page: Dissection Here are defined the docker\u0026rsquo;s networks:\n## docker-compose.yaml ##\r3networks: 4 my-external-network: 5 external: true 6 my-internal-network: 7 external: false\rThe my-external-network is the only one exposed to the outside and is used by the nginx container to communicate with Traefik:\n## docker-compose.yaml ##\r9services: 10 nginx: 11 image: nginx:alpine 12 container_name: nginx 13 volumes: 14 # Mount the application source code into the Nginx container. 15 - ./public:/var/www/html 16 # Mount the custom Nginx configuration file. 17 - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro 18 networks: 19 - my-external-network 20 - my-internal-network\rThe other one (my-internal-network) is found in both nginx and php-fpm containers and is used only for a communication between the two:\n## docker-compose.yaml ##\r31 php-fpm: 32 image: php:8.3-fpm-alpine 33 container_name: php-fpm 34 volumes: 35 # Mount the application source code into the PHP-FPM container. 36 - ./public:/var/www/html 37 networks: 38 - my-internal-network\rIn the Nginx configuration, the highlighted line is probably the most important one. It indicates which docker host should receive *.php requests, and on which port\n## default.conf ##\r14 # This location block specifically handles files ending in .php. 15 location ~ \\.php$ { 16 # Ensure the file exists to prevent arbitrary code execution. 17 try_files $uri =404; 18 19 # Pass the request to the PHP-FPM service. 20 fastcgi_pass php-fpm:9000;\rHere is a simple test showing that php-fpm is set to processing requests\n## index.php ##\r54 \u0026lt;?php 55 ob_start(); 56 phpinfo(); 57 $php_info = ob_get_clean(); 58 59 $lines = explode(\u0026#34;\\n\u0026#34;, $php_info); 60 foreach ($lines as $line) { 61 if (strpos($line, \u0026#39;Server API\u0026#39;) !== false) { 62 echo htmlspecialchars($line); 63 break; 64 } 65 } 66 ?\u0026gt; Wrapping up As we\u0026rsquo;ve seen, setting up a modern web stack with Docker, Traefik, Nginx, and PHP-FPM is a powerful way to build a robust and scalable application. It represents a fundamental shift away from monolithic, all-in-one web servers to a more efficient, decoupled architecture.\nThis separation of concerns is the key benefit. It means you can scale each part of your application independently, ensuring your website remains performant and resilient under heavy load.\n","permalink":"/posts/traefik/php-fpm/","tags":[{"LinkTitle":"Traefik","RelPermalink":"/tags/traefik/"},{"LinkTitle":"PHP-FPM","RelPermalink":"/tags/php-fpm/"},{"LinkTitle":"Docker","RelPermalink":"/tags/docker/"},{"LinkTitle":"Docker Compose","RelPermalink":"/tags/docker-compose/"},{"LinkTitle":"Nginx","RelPermalink":"/tags/nginx/"}],"title":"Dockerized PHP-FPM \u0026 Nginx through Traefik"},{"categories":[{"LinkTitle":"DevOps","RelPermalink":"/categories/devops/"}],"content":"Goals Locally configure and run a dockerized Traefik reverse proxy over TLS Deploy the setup on a real domain name Quick overview Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices a breeze. It\u0026rsquo;s designed to integrate seamlessly with your existing infrastructure components, and it\u0026rsquo;s particularly powerful when combined with Docker.\nAt its core, Traefik works by dynamically discovering your services and routing requests to them. Instead of manually configuring each service endpoint, Traefik monitors your Docker daemon (or other orchestrators like Kubernetes, Swarm, Mesos, etc.) for changes. When a new container is launched or an existing one is stopped, Traefik automatically updates its routing rules. You can check their official documentation here: https://doc.traefik.io/traefik/ Overview of Traefik/Docker relationship\rSource code Here you\u0026rsquo;ll find the full source code for a ready to launch Treafik reverse proxy, with an automatic TLS certificates generation provider: https://github.com/a-naitslimane/anaitslimane.article.reverse-proxy-traefik-docker.git Note:\nThere are many ways to run/deploy docker containers. Here, I will exclusively be using docker compose.\nLocal Setup Prerequisites: Docker and Docker Compose installed on your machine Setup Clone the source code to your working-directory\nSet environment variables\nCreate a copy of .env.exemple named .env. In it, you can set your own values of course, as long as they are consistent with the rest of the following config.\nThe DOMAIN_NAME value in particular\nBind your DOMAIN_NAME to the localhost:\nAdd these two lines to the hosts file: C:\\Windows\\System32\\drivers\\etc\\hosts (on Windows) and /etc/hosts (on Linux).\n127.0.0.1 \u0026lt;local-domain-name\u0026gt;\r127.0.0.1 \u0026lt;dashboard-prefix\u0026gt;.\u0026lt;local-domain-name\u0026gt;\rFor example:\n127.0.0.1 my-local-domain.com\r127.0.0.1 my-dashboard-prefix.my-local-domain.com\rCreate the common (external) network which will be used by all services managed by Traefik:\nOpen a terminal and type in: docker network create my-external-network\rLaunch the services using docker compose:\nIn your terminal, first cd to your working-directory then type: docker compose -f docker-compose.yaml -f docker-compose.local.yaml up\rTesting Check that both the traefik-reverse-proxy and traefik-mkcert containers are running and healthy.\nCheck your certs directory, if eveything went fine, it should now be populated with local certificates. If you check in the logs (here I am using Docker Desktop) you should have this: Open the following address in your browser: http://localhost:8080/dashboard/\nYou should be seeing the following dashboard: Deploy on a Real Domain Prerequisites: SSH access to a deployment/hosting server A registered domain name Docker and Docker Compose installed on your deployment/hosting server Setup From now on, everything that follows (commands/instructions) will of course assume you are on a terminal connected to your remote server through SSH\nOptional: Secure the dashboard access using a BasicAuth authentication (you need to have htpasswd installed)\nGenerate the TRAEFIK_CREDENTIALS echo $(htpasswd -nb \u0026lt;your-username\u0026gt; \u0026lt;your-pwd\u0026gt;) | sed -e s/\\\\$/\\\\$\\\\$/g\rRemember/save the values you entered for the \u0026lt;your-username\u0026gt; and \u0026lt;your-pwd\u0026gt; as they wil be the values needed to access your dashboard respectively for the username and password. Clone (or remote copy) the source code to your server\u0026rsquo;s working-directory of choice\nSet environment variables:\nCreate a copy of .env.exemple named .env and set the correct values within it: ENV=prod. Your own DOMAIN_NAME Your own DASHBOARD_PREFIX If applicable, the previously generated value for TRAEFIK_CREDENTIALS Create the common (external) network which will be used by all services managed by Traefik:\nIn your ssh terminal, type in: docker network create my-external-network\rSet your own contact email\n## docker-compose.prod.yaml ##\r64 ############################################################################################## 65 # tlschallenge challenge 66 ############################################################################################## 67 # Email address used for registration. 68 # 69 # Required 70 # 71 #- \u0026#34;--certificatesresolvers.tlsResolver.acme.email=/secrets/cert_contact_email\u0026#34; 72 - \u0026#34;--certificatesresolvers.tlsResolver.acme.email=contact@my-domain.com\u0026#34;\rThis email should be a real one, you cannot use a fake one even for the staging servers\nSet the TLS certificate servers\nIn order to avoid exceeding the rate limit set on Let\u0026rsquo;s Encrypt production servers, it is advisable to first try out and make all your tests using the Let\u0026rsquo;s Encrypt staging servers:\n## docker-compose.prod.yaml ##\r80 # CA server to use. 81 # Uncomment the line to use Let\u0026#39;s Encrypt\u0026#39;s staging server, 82 # leave commented to go to prod. 83 # 84 # Optional 85 # Default: \u0026#34;https://acme-v02.api.letsencrypt.org/directory\u0026#34; 86 # Staging: \u0026#34;https://acme-staging-v02.api.letsencrypt.org/directory\u0026#34; 87 # 88 - \u0026#34;--certificatesresolvers.tlsResolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory\u0026#34;\rPrepare your Traefik dashboard access subdomain:\nGo to your domain provider DNS zone and add a CNAME entry which will be the Traefik dashboard For example, if your domain name is \u0026ldquo;my-domain-name.com\u0026rdquo; and the DASHBOARD_PREFIX is \u0026ldquo;my-traefik-dashboard\u0026rdquo;, you need to add \u0026ldquo;my-traefik-dashboard.my-domain-name.com\u0026rdquo; as a CNAME and point it to \u0026ldquo;my-domain-name.com\u0026rdquo; Launch Traefik in production:\nIn your terminal, first cd to your working-directory then type: docker compose -f docker-compose.yaml -f docker-compose.prod.yaml up\rImportant! Be aware that the staging server\u0026rsquo;s configuration will emit valid certificates, however not trusted by your browsers. When accessing your domain (and subdomains), you will have a warning NET::ERR_CERT_AUTHORITY_INVALID that you\u0026rsquo;d need to bypass in order to accept the certificates as trusted ones.\nOnce everything is tested out and in full order using the staging servers, put back the production servers url (Default): \u0026ldquo;https://acme-v02.api.letsencrypt.org/directory\" Testing Check that the traefik-reverse-proxy container is running and healthy. Access your dashboard at: https://my-traefik-dashboard.my-domain-name.com/dashboard/ (of course replace with your own real subdomain address) If you\u0026rsquo;ve set the BasicAuth, you\u0026rsquo;d of course need to provide your username/password set previously in order to be authenticated\nCheck the acme.json file ssh to your server and access your reverse proxy container: docker exec -it prod-traefik-reverse-proxy sh\rNow, if you open the acme.json file, it should have the certificates for both your main domain and your subdomain (Traefik dashboard): cat /letsencrypt/acme.json\rFurther dissection Here we basically redirect all http (port 80) requests to https (port 443) :\n## docker-compose.local.yaml ##\r11- \u0026#34;--entryPoints.web.address=:80\u0026#34; 12- \u0026#34;--entryPoints.web.http.redirections.entryPoint.to=websecure\u0026#34; 13- \u0026#34;--entryPoints.web.http.redirections.entryPoint.scheme=https\u0026#34; 14- \u0026#34;--entryPoints.websecure.address=:443\u0026#34;\rSpecifically for the production config, we inforce https as default entrypoint, and the TLS certResolver :\n## docker-compose.prod.yaml ##\r23 - \u0026#34;--entryPoints.web.address=:80\u0026#34; 24 - \u0026#34;--entryPoints.web.http.redirections.entryPoint.to=websecure\u0026#34; 25 - \u0026#34;--entryPoints.web.http.redirections.entryPoint.scheme=https\u0026#34; 26 - \u0026#34;--entryPoints.websecure.address=:443\u0026#34; 27 - \u0026#34;--entrypoints.websecure.asDefault=true\u0026#34; 28 - \u0026#34;--entrypoints.websecure.http.tls.certResolver=tlsResolver\u0026#34;\rLocally, the TLS certificates generation is handled by a third party tool mkcert, here:\n## docker-compose.local.yaml ##\r38traefik-mkcert: 39 image: vishnunair/docker-mkcert 40 container_name: traefik-mkcert 41 42 environment: 43 - domain=${DOMAIN_NAME}, *.${DOMAIN_NAME} 44 volumes: 45 - ./certs/:/root/.local/share/mkcert 46 labels: 47 - \u0026#34;traefik.enable=false\u0026#34; 48 networks: 49 - my-external-network\rYou can find the repo here: vishnunair/docker-mkcert Also since both traefik-reverse-proxy and traefik-mkcert containers map a volume to the host\u0026rsquo;s \u0026ldquo;certs\u0026rdquo; directory, the traefik-reverse-proxy container can read the certificates generated by the traefik-mkcert container:\n## docker-compose.local.yaml ##\rtraefik-reverse-proxy: ... ... volumes: - ./certs/:/etc/certs:ro ... ... traefik-mkcert: ... ... volumes: - ./certs/:/root/.local/share/mkcert ... ...\rLocally, we are mapping an extra port 8080:\n## docker-compose.local.yaml ##\r33 ports: 34 - \u0026#34;80:80\u0026#34; 35 - \u0026#34;443:443\u0026#34; 36 - \u0026#34;8080:8080\u0026#34;\rIts scope sits outside of the global entryPoints configuration, thus allowing us to locally access the dashboard directly through http:\n## docker-compose.local.yaml ##\r5 command: 6 - \u0026#34;--api.dashboard=true\u0026#34; 7 - \u0026#34;--api.insecure=true\u0026#34; 8 9 - \u0026#34;--serversTransport.insecureSkipVerify=true\u0026#34;\rOn the production side, the acme.json file might have permissions issues if we leave it on its own, that\u0026rsquo;s the reason why we enforce its permissions management at runtime:\n## entrypoint.sh ##\r1#! /bin/sh 2set -e 3 4echo \u0026#34;Setting acme.json permissions 0600\u0026#34; 5touch /letsencrypt/acme.json 6chmod 600 /letsencrypt/acme.json 7chown root:root /letsencrypt 8chown root:root /letsencrypt/acme.json\rWrapping up We have been able to quickly setup a ready to use Traefik reverse proxy with an automatic Let\u0026rsquo;s Encrypt certificates generation. Both locally and on a live server/domain.\nThe next step is to add a service (Docker container) configured in the same network as the presented reverse proxy and watch how auto-magically it is recognized and taken care of by Traefik.\n","permalink":"/posts/traefik/setup/","tags":[{"LinkTitle":"Traefik","RelPermalink":"/tags/traefik/"},{"LinkTitle":"Reverse Proxy","RelPermalink":"/tags/reverse-proxy/"},{"LinkTitle":"Docker","RelPermalink":"/tags/docker/"},{"LinkTitle":"Docker Compose","RelPermalink":"/tags/docker-compose/"},{"LinkTitle":"Let's Encrypt","RelPermalink":"/tags/lets-encrypt/"}],"title":"Reverse Proxy using Traefik and Docker"},{"categories":[],"content":"","permalink":"/manifest.json","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.de/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.es/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.hi/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.jp/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.nl/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.pl/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.ru/","tags":[],"title":""},{"categories":[],"content":"","permalink":"/search/_index.zh-cn/","tags":[],"title":""},{"categories":[],"content":"Welcome to my personal tech blog. Here you can find a few of my fiddling abouts.\nI am a highly experienced developer (web in particular) and have started fiddling about in my spare time with JAVASCRIPT and PHP back in 2008 besides my formal training which was mainly in JAVA. Since then, I\u0026rsquo;ve put my hands on a multitude of web/mobile frameworks whether it be front or backend, learning them on the go. My methodology is very simple: learning by doing.\nI also had the opportunity to lead a few developers teams and participate in project management on several other occasions.\nMy satisfaction comes from sharing my knowledge so if my work here helps at least someone then my duty is fullfiled.\n","permalink":"/about/","tags":[],"title":"About"},{"categories":[{"LinkTitle":"DevOps","RelPermalink":"/fr/categories/devops/"}],"content":"Objectifs Configurer une instance Jenkins entièrement dockerisée comprenant un Controller (Master) et un Agent (Slave). Router l\u0026rsquo;ensemble via notre proxy inverse Traefik mis en place précédemment. Introduction Avant de passer au cœur de la configuration, introduisons quelques concepts clés.\nLes pipelines CI/CD modernes font face à un défi majeur : créer un environnement de build cohérent, propre et reproductible. Les méthodes traditionnelles mènent souvent à des conflits de dépendances et au fameux problème \u0026ldquo;ça marche sur ma machine\u0026rdquo;.\nDocker apporte la solution idéale en isolant les applications et leurs dépendances dans des conteneurs. En combinant Jenkins, le serveur d\u0026rsquo;automatisation de référence, avec Docker, nous créons un système CI/CD puissant et flexible.\nCette intégration peut se faire de deux manières principales :\nJenkins à l\u0026rsquo;intérieur d\u0026rsquo;un conteneur Docker qui possède son propre démon Docker (Docker-in-Docker ou DinD).\nJenkins à l\u0026rsquo;intérieur d\u0026rsquo;un conteneur Docker qui utilise le démon Docker de l\u0026rsquo;hôte (Docker-out-of-Docker ou DoD).\nVoici une comparaison rapide entre DinD et DoD dans le contexte de Jenkins : Caractéristique Docker-in-Docker (DinD) Docker-out-of-Docker (DoD) Fonctionnement Le conteneur Jenkins exécute son propre démon Docker imbriqué. Le conteneur Jenkins utilise le démon Docker de l\u0026rsquo;hôte. Sécurité ⚠️ Expertise requise ! Nécessite le drapeau --privileged. ✅ Direct. Pas de mode privilégié nécessaire. Performance 🔻 Moyenne. Surcharge due aux démons multiples ; pas de cache partagé. ✅ Excellente. Démon unique et cache d\u0026rsquo;images partagé. Isolation ✅ Totale. Chaque build est isolé de l\u0026rsquo;hôte et des autres jobs. 🔻 Limitée. Tous les conteneurs sont \u0026ldquo;frères\u0026rdquo; sur le même hôte. Important ! Cet article couvrira exclusivement l\u0026rsquo;approche DoD. De plus, pour garder les choses simples, j\u0026rsquo;utiliserai le même hôte pour le Controller et l\u0026rsquo;Agent.\nCode source Vous trouverez ici le code source pour une installation Jenkins complète :\nController (master) : https://github.com/a-naitslimane/anaitslimane.article.jenkins-traefik-docker.jenkins-controller Agent (slave) : https://github.com/a-naitslimane/anaitslimane.article.jenkins-traefik-docker.jenkins-agent Configuration Prérequis : Docker et Docker Compose installés sur votre machine. Un proxy inverse Traefik dockerisé tournant localement. Si ce n\u0026rsquo;est pas le cas, veuillez suivre mon article précédent Traefik reverse proxy . Important ! Les configurations suivantes sont étroitement liées aux paramètres de mon article précédent. Pensez à les ajuster avec vos propres valeurs, en particulier le nom du réseau Docker externe.\nMise en place des conteneurs Clonez le code source vers votre répertoire de travail.\nDéfinissez les variables d\u0026rsquo;environnement\nCréez une copie de .env.example nommée .env. Vous pouvez y définir vos propres valeurs, tant qu\u0026rsquo;elles restent cohérentes avec la suite de la configuration.\nLiez votre DOMAIN_NAME au localhost :\nAjoutez votre nom de domaine local au fichier hosts : C:\\Windows\\System32\\drivers\\etc\\hosts (sur Windows) ou /etc/hosts (sur Linux).\n127.0.0.1 ci-cd-ctrl.my-local-domain.com\rLancez le service via Docker Compose :\nDans votre terminal, cd vers votre répertoire de travail puis tapez simplement : docker compose up\rTest du Controller Vérifiez que le conteneur du controller est actif et sain. Récupérez le mot de passe généré par défaut. Dans votre navigateur, ouvrez l\u0026rsquo;adresse configurée dans DOMAIN_NAME (ex: ci-cd-ctrl.my-local-domain.com). Saisissez le mot de passe récupéré à l\u0026rsquo;étape précédente. Choisissez votre méthode préférée pour l\u0026rsquo;installation des plugins. Notez que vous pourrez gérer les plugins plus tard. Complétez votre profil administrateur. Configurez l\u0026rsquo;URL Jenkins avec la valeur de votre DOMAIN_NAME (ex: ci-cd-ctrl.my-local-domain.com). Quid de l\u0026rsquo;Agent (Node) ? Il existe deux méthodes pour lier l\u0026rsquo;agent au controller via le Launch method. La première demande à l\u0026rsquo;agent de se connecter au controller, ce qui nécessite l\u0026rsquo;ouverture et la configuration d\u0026rsquo;un port entrant sur le controller. Veuillez consulter la documentation jenkins/ssh-agent pour ce cas.\nPour cet article, j\u0026rsquo;ai délibérément choisi la seconde option ! Celle-ci fonctionne à l\u0026rsquo;inverse : c\u0026rsquo;est le controller qui se connecte à l\u0026rsquo;agent via SSH. Pour y parvenir, nous devons créer ce que l\u0026rsquo;on appelle dans Jenkins des credentials (identifiants). Consultez la doc Jenkins pour en savoir plus sur la gestion des identifiants .\nParmi les options disponibles, j\u0026rsquo;ai choisi \u0026ldquo;SSH Username with private key\u0026rdquo;. Cela nécessite la création d\u0026rsquo;une paire de clés SSH à utiliser entre le controller et l\u0026rsquo;agent.\nMaintenant que le contexte est posé, passons à la pratique :\nPréparation de la configuration SSH Connectez-vous à la console du conteneur controller (bash est disponible dans l\u0026rsquo;image) :\ndocker exec -it ci-cd-jenkins-ctrl bash\rGénérez la clé (j\u0026rsquo;ai choisi l\u0026rsquo;algorithme ssh-ed25519) avec la commande suivante. Laissez la \u0026ldquo;passphrase\u0026rdquo; vide pour éviter toute complication inutile pour le moment.\nssh-keygen -t ed25519 -C \u0026#34;jenkins\u0026#34;\rCela générera la paire de clés (privée/publique). Le répertoire par défaut de sauvegarde devrait être \u0026rsquo;/var/jenkins_home/.ssh\u0026rsquo;.\nAjout des identifiants Allez sur le tableau de bord du controller. Cliquez sur Administrer Jenkins \u0026gt; Credentials. Vous pouvez créer un domaine spécifique ou, pour faire simple, choisir le domaine par défaut Global credentials (unrestricted). Cliquez sur Add Credentials. Sélectionnez l\u0026rsquo;option SSH Username with private key. Entrez jenkins dans le champ Username. Pour la Private Key, sélectionnez Enter directly. Cliquez sur Add, puis copiez-collez l\u0026rsquo;intégralité de la clé privée générée précédemment pour l\u0026rsquo;utilisateur jenkins. Ajout de l\u0026rsquo;Agent (Node) Retournez sur le tableau de bord. Dans le menu de gauche, cliquez sur le lien Build executor Status. Cliquez sur New Node, donnez-lui un nom, sélectionnez Permanent Agent et validez. Remplissez les champs requis, notamment : \u0026ldquo;Launch method\u0026rdquo; : Launch agent via SSH. \u0026ldquo;Host\u0026rdquo; : le nom du conteneur agent ci-cd-jenkins-ssh-agent. \u0026ldquo;Remote root directory\u0026rdquo; : /home/jenkins/agent. Sélectionnez les credentials créés précédemment. Pour \u0026ldquo;Host Key Verification Strategy\u0026rdquo;, j\u0026rsquo;ai choisi Manually trusted key Verification Strategy. Lancement du conteneur Docker de l\u0026rsquo;agent Clonez le code source . Définissez les variables d\u0026rsquo;environnement (copie de .env.example vers .env). Configurez notamment la valeur SSH_PUBKEY avec la clé publique générée précédemment depuis l\u0026rsquo;interface du controller. ## env ##\r1PORT_JENKINS_AGENT_SSH=22 2COMPOSE_PROJECT_NAME=ci-cd-jenkins-ssh-agent 3DOCKER_GROUP_ID=0 4SSH_PUBKEY=\u0026lt;votre_clé_publique_ici\u0026gt;\rLancez l\u0026rsquo;agent : docker compose up\rTest de l\u0026rsquo;agent Allez sur le tableau de bord du controller. Sélectionnez votre agent. Cliquez sur le bouton Launch agent et voilà ! Votre agent est connecté. Pièges courants Basique Clé publique erronée : Une erreur de frappe de la clé publique empêchera toute connexion. Il est crucial de respecter scrupuleusement le format attendu par le conteneur agent. Solution : Vérifiez que la clé commence bien par son type (ex: ssh-ed25519) et qu\u0026rsquo;elle ne contient pas de retours à la ligne parasites dans votre fichier .env. Format de la clé privée : Lors de la création des identifiants (Credentials) dans Jenkins, l\u0026rsquo;ajout d\u0026rsquo;espaces superflus ou de sauts de ligne incorrects invalidera la clé. Solution : Copiez l\u0026rsquo;intégralité du bloc, y compris les balises -----BEGIN... et ...END-----, sans modification manuelle du contenu. Configuration du Port SSH : Lors de la déclaration du Node sur le dashboard Jenkins, la connexion échouera si le port ne correspond pas à celui exposé par le conteneur de l\u0026rsquo;agent. Solution : Assurez-vous que le champ \u0026ldquo;Port\u0026rdquo; dans Jenkins correspond exactement à la valeur PORT_JENKINS_AGENT_SSH définie dans votre configuration Docker (par défaut 22). Avancé Permissions du Socket Docker (Conflit de GID) : Dans une configuration DoD, l\u0026rsquo;agent doit pouvoir communiquer avec /var/run/docker.sock sur l\u0026rsquo;hôte. Si l\u0026rsquo;ID de groupe (GID) du groupe \u0026ldquo;docker\u0026rdquo; de l\u0026rsquo;hôte ne correspond pas au DOCKER_GROUP_ID de votre .env, vous ferez face à des erreurs \u0026ldquo;Permission Denied\u0026rdquo;. Solution : Lancez stat -c '%g' /var/run/docker.sock sur votre hôte et mettez à jour votre .env avec cette valeur numérique. Ports SSH non standards : Si vous avez modifié le PORT_JENKINS_AGENT_SSH dans le .env de l\u0026rsquo;agent pour une valeur autre que 22, Jenkins ne pourra pas se connecter. Solution : Vérifiez que le champ \u0026ldquo;Port\u0026rdquo; dans la configuration du Node Jenkins correspond exactement au port SSH exposé par votre conteneur. Conteneurs de Build \u0026ldquo;Zombies\u0026rdquo; : Comme les conteneurs de build sont des \u0026ldquo;frères\u0026rdquo; sur l\u0026rsquo;hôte, un crash de l\u0026rsquo;agent peut laisser des conteneurs orphelins en cours d\u0026rsquo;exécution. Solution : Auditez périodiquement votre hôte avec docker ps pour vous assurer qu\u0026rsquo;aucun processus de build ne consomme de ressources inutilement après l\u0026rsquo;échec d\u0026rsquo;un pipeline. Connectivité réseau Traefik : Le Controller Jenkins doit pouvoir atteindre le conteneur Agent. S\u0026rsquo;ils ne sont pas sur le même réseau Docker, la connexion SSH échouera (Time out). Solution : Vérifiez que les deux services sont connectés au même réseau docker externe défini dans vos fichiers Compose. En résumé En routant votre Controller et votre Agent Jenkins via Traefik, vous avez dépassé le stade du simple lab pour mettre en place un environnement CI/CD professionnel avec proxy inverse. L\u0026rsquo;approche DoD garantit la rapidité de vos builds grâce au partage du cache d\u0026rsquo;images de l\u0026rsquo;hôte, tandis que la configuration de l\u0026rsquo;Agent via SSH maintient une architecture découplée et sécurisée.\nNote finale:\nÉvolutivité : Vous pouvez désormais passer à l\u0026rsquo;échelle horizontalement en ajoutant d\u0026rsquo;autres agents via le même modèle SSH sur différents hôtes. Maintenance : Puisque les conteneurs de build sont des \u0026ldquo;frères\u0026rdquo; sur votre hôte, pensez à exécuter un docker image prune occasionnellement pour garder votre environnement propre. Vous disposez maintenant d\u0026rsquo;une stack d\u0026rsquo;automatisation robuste et dockerisée, prête à propulser vos pipelines les plus complexes. Bonne automatisation !\n","permalink":"/fr/posts/traefik/jenkins/","tags":[{"LinkTitle":"Jenkins","RelPermalink":"/fr/tags/jenkins/"},{"LinkTitle":"Docker","RelPermalink":"/fr/tags/docker/"},{"LinkTitle":"Docker Compose","RelPermalink":"/fr/tags/docker-compose/"},{"LinkTitle":"Traefik","RelPermalink":"/fr/tags/traefik/"}],"title":"Installation complète de Jenkins sous Docker via Traefik"},{"categories":[{"LinkTitle":"DevOps","RelPermalink":"/fr/categories/devops/"}],"content":"Objectif Montrer comment s\u0026rsquo;articule le ballet PHP-FPM - Nginx afin de répondre aux requêtes web dans un environnement dockerisé, tout cela à travers notre reverse proxy Traefik Introduction La spécificité de PHP-FPM PHP-FPM (FastCGI Process Manager) Le point clé réside dans l\u0026rsquo;approche architecturale de PHP.\nMéthode traditionnelle: Dans une configuration traditionnelle (par exemple, Apache avec mod_php), le serveur web et l\u0026rsquo;interpréteur PHP ne forment qu\u0026rsquo;un seul processus monolithique. À chaque nouvelle requête web, un nouveau processus Apache est créé, lequel contient l\u0026rsquo;intégralité du moteur PHP. Cette approche est simple à mettre en place, mais elle consomme beaucoup de ressources et n\u0026rsquo;est pas très efficace pour gérer un grand nombre de requêtes.\nMéthode PHP-FPM: PHP-FPM sépare les responsabilités. Le serveur web (Nginx) est optimisé pour ce qu\u0026rsquo;il fait de mieux (servir des fichiers), et PHP-FPM est un pool de processus distinct et dédié, optimisé pour l\u0026rsquo;exécution de PHP. Cette approche permet à chaque composant d\u0026rsquo;être extrêmement performant et évolutif. En cas de forte charge, vous pouvez simplement augmenter la capacité du service PHP-FPM sans affecter le serveur web. Cette méthode est bien plus efficace et résiliente pour les applications web modernes.\nLe Request Flow Une requête arrive dans Traefik sur le port 443 (HTTPS), qui la déchiffre et l\u0026rsquo;envoie à Nginx. Nginx, agissant comme un proxy, transfère la requête à PHP-FPM via un réseau interne privé. PHP-FPM exécute le code, renvoie le résultat à Nginx, et Nginx transmet le contenu final à Traefik, qui le chiffre à nouveau et le délivre à l\u0026rsquo;utilisateur. Comme illustré dans le diagramme suivant.\nVue d'ensemble du workflow Docker - Traefik - Nginx - PHP-FPM\rSource code Vous trouverez ici le code source d\u0026rsquo;une page de démonstration PHP simple, montrant comment les différents conteneurs fonctionnent ensemble pour gérer les requêtes: https://github.com/a-naitslimane/anaitslimane.article.php-fpm-traefik-docker Setup Prérequis: Docker et Docker Compose installés sur votre machine Un reverse proxy Traefik dockerisé tournant en local. Si vous ne l\u0026rsquo;avez pas déjà, veuillez vous réferer à mon précédent article Traefik reverse proxy Important! Les configurations suivantes sont fortement liées aux configurations de mon précédent article. N\u0026rsquo;oubliez pas de les ajuster avec vos propres valeurs, en particulier le nom de réseau docker externe\nConfiguration locale Cloner le code source dans votre répertoire de travail\nDéfinir les variables d’environnement\nCréez une copie de .env.exemple nommée .env. Vous pouvez y définir vos propres valeurs, bien sûr, à condition qu’elles soient cohérentes avec le reste de la configuration.\\\nLier votre DOMAIN_NAME au localhost:\nAjoutez votre domaine local au fichier hosts : C:\\Windows\\System32\\drivers\\etc\\hosts (sous Windows) et /etc/hosts (sous Linux).\n127.0.0.1 php-fpm.demo.domain\rLancer les services avec docker compose:\nDans votre terminal, placez-vous dans votre répertoire de travail et exécutez: docker compose -f docker-compose.yaml -f up\rTests Vérifiez que les conteneurs nginx et php-fpm sont en cours d’exécution et en bonne santé.\nOuvrez l\u0026rsquo;adresse que vous aviez configuré en tant que DOMAIN_NAME dans votre navigateur web (ex: https://php-fpm.demo.domain )\nVous devriez avoir cette page: Analyse Les réseaux Docker sont définis ici:\n## docker-compose.yaml ##\r3networks: 4 my-external-network: 5 external: true 6 my-internal-network: 7 external: false\rLe my-external-network est le seul exposé à l\u0026rsquo;extérieur et est utilisé par le conteneur nginx pour communiquer avec Traefik:\n## docker-compose.yaml ##\r9services: 10 nginx: 11 image: nginx:alpine 12 container_name: nginx 13 volumes: 14 # Mount the application source code into the Nginx container. 15 - ./public:/var/www/html 16 # Mount the custom Nginx configuration file. 17 - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro 18 networks: 19 - my-external-network 20 - my-internal-network\rL\u0026rsquo;autre réseau (my-internal-network) est propre aux deux conteneurs nginx et php-fpm et sert uniquement à ces derniers pour communiquer entre-eux:\n## docker-compose.yaml ##\r31 php-fpm: 32 image: php:8.3-fpm-alpine 33 container_name: php-fpm 34 volumes: 35 # Mount the application source code into the PHP-FPM container. 36 - ./public:/var/www/html 37 networks: 38 - my-internal-network\rDans la configuration de Nginx suivante, la ligne clé est en surbrillance. Elle indique quel hôte Docker doit recevoir les requêtes .php et sur quel port\n## default.conf ##\r14 # This location block specifically handles files ending in .php. 15 location ~ \\.php$ { 16 # Ensure the file exists to prevent arbitrary code execution. 17 try_files $uri =404; 18 19 # Pass the request to the PHP-FPM service. 20 fastcgi_pass php-fpm:9000;\rVoici un test simple montrant que php-fpm est configuré pour traiter les requêtes\n## index.php ##\r54 \u0026lt;?php 55 ob_start(); 56 phpinfo(); 57 $php_info = ob_get_clean(); 58 59 $lines = explode(\u0026#34;\\n\u0026#34;, $php_info); 60 foreach ($lines as $line) { 61 if (strpos($line, \u0026#39;Server API\u0026#39;) !== false) { 62 echo htmlspecialchars($line); 63 break; 64 } 65 } 66 ?\u0026gt; Pour conclure La mise en place d\u0026rsquo;une stack web moderne avec Docker, Traefik, Nginx et PHP-FPM est une approche puissante pour construire une application robuste et évolutive. Elle représente un changement fondamental, passant des serveurs web monolithiques tout-en-un à une architecture plus efficace et découplée.\nCette séparation des responsabilités est l\u0026rsquo;avantage clé. Elle vous permet de faire évoluer chaque partie de votre application de manière indépendante, garantissant ainsi que votre site web reste performant et résilient en cas de forte charge.\n","permalink":"/fr/posts/traefik/php-fpm/","tags":[{"LinkTitle":"Traefik","RelPermalink":"/fr/tags/traefik/"},{"LinkTitle":"PHP-FPM","RelPermalink":"/fr/tags/php-fpm/"},{"LinkTitle":"Docker","RelPermalink":"/fr/tags/docker/"},{"LinkTitle":"Docker Compose","RelPermalink":"/fr/tags/docker-compose/"},{"LinkTitle":"Nginx","RelPermalink":"/fr/tags/nginx/"}],"title":"PHP-FPM \u0026 Nginx \u0026 Traefik, sous Docker"},{"categories":[{"LinkTitle":"DevOps","RelPermalink":"/fr/categories/devops/"}],"content":"Objectifs Configurer et lancer localement un reverse proxy Traefik dockerisé doté de certificats TLS générés automatiquement Déployer le tout sur un nom de domaine réel Introduction rapide Traefik est un reverse proxy HTTP moderne doublé d\u0026rsquo;un load balancer qui facilite le déploiement de microservices. Il est conçu pour s’intégrer parfaitement à vos composants d’infrastructure existants, et devient particulièrement puissant lorsqu’il est utilisé avec Docker.\nAu cœur de son fonctionnement, Traefik procède avec une capacité de découverte dynamique de vos services (conteneurs) et leur achemine les requêtes correspondantes. Plutôt que de configurer manuellement chaque endpoint, Traefik surveille votre démon Docker (ou d\u0026rsquo;autres orchestrateurs comme Kubernetes, Swarm, Mesos, etc.) pour détecter les changements. Lorsqu’un nouveau conteneur est lancé ou qu’un conteneur existant est arrêté, Traefik met automatiquement à jour ses règles de routage. Vous pouvez consulter la documentation officielle ici : https://doc.traefik.io/traefik/ Vue d'ensemble de la relation Traefik/Docker\rCode source Vous trouverez ici le code source complet pour un reverse proxy Traefik prêt à l\u0026rsquo;emploi, avec génération automatique de certificats TLS : https://github.com/a-naitslimane/anaitslimane.article.reverse-proxy-traefik-docker.git Note:\nIl existe de nombreuses façons d\u0026rsquo;exécuter/déployer des conteneurs Docker. Ici, j\u0026rsquo;utiliserai exclusivement docker compose.\nConfiguration locale Prérequis : Docker et Docker Compose installés sur votre machine Etapes Cloner le code source dans votre répertoire de travail\nDéfinir les variables d’environnement\nCréez une copie de .env.exemple nommée .env Vous pouvez y définir vos propres valeurs, bien sûr, à condition qu’elles soient cohérentes avec le reste de la configuration. Notamment la valeur DOMAIN_NAME\nLier votre DOMAIN_NAME au localhost :\nAjoutez ces deux lignes au fichier hosts : C:\\Windows\\System32\\drivers\\etc\\hosts (sous Windows) et /etc/hosts (sous Linux).\n127.0.0.1 \u0026lt;nom-domaine-local\u0026gt;\r127.0.0.1 \u0026lt;prefixe-dashboard\u0026gt;.\u0026lt;nom-domaine-local\u0026gt;\rPar exemple : 127.0.0.1 mon-domaine-local.com\r127.0.0.1 mon-prefixe-dashboard.mon-domaine-local.com\rCréer le réseau commun (externe) utilisé par tous les services gérés par Traefik:\nOuvrez un terminal et tapez : docker network create my-external-network\rLancer les services avec docker compose :\nDans votre terminal, placez-vous dans votre répertoire de travail et exécutez : docker compose -f docker-compose.yaml -f docker-compose.local.yaml up\rTests Vérifiez que les conteneurs traefik-reverse-proxy et traefik-mkcert sont en cours d’exécution et en bonne santé.\nVérifiez votre dossier certs : s’il s\u0026rsquo;est doté de certificats locaux, c’est que tout s’est bien passé.\nDans les logs (ici via Docker Desktop), vous devriez voir ceci : Ouvrez l’adresse suivante dans votre navigateur : http://localhost:8080/dashboard/\nVous devriez voir le tableau de bord suivant : Déploiement sur un Domaine Réel Prérequis : Accès SSH à un serveur de déploiement/hébergement Un nom de domaine enregistré Docker et Docker Compose installés sur le serveur Configuration À partir de maintenant, toutes les commandes/instructions supposent que vous êtes connecté à votre serveur distant via SSH.\nOptionnel : Sécurisez l\u0026rsquo;accès au tableau de bord via une authentification BasicAuth (vous devez avoir htpasswd installé)\nGénérer les TRAEFIK_CREDENTIALS echo $(htpasswd -nb \u0026lt;votre-nom-utilisateur\u0026gt; \u0026lt;votre-mot-de-passe\u0026gt;) | sed -e s/\\\\$/\\\\$\\\\$/g\rNotez les valeurs utilisées pour \u0026lt;votre-nom-utilisateur\u0026gt; et \u0026lt;votre-mot-de-passe\u0026gt;, elles seront nécessaires pour accéder au tableau de bord. Cloner (ou copier à distance) le code source dans le répertoire de travail de votre choix sur votre serveur\nDéfinir les variables d’environnement :\nCréez une copie de .env.exemple nommée .env et remplissez-la avec : ENV=prod Votre propre DOMAIN_NAME Votre propre DASHBOARD_PREFIX Le cas échéant, la valeur générée pour TRAEFIK_CREDENTIALS Créer le réseau commun (externe) utilisé par tous les services gérés par Traefik :\nDans votre terminal ssh entrez : docker network create my-external-network\rDéfinir votre adresse e-mail de contact :\n## docker-compose.prod.yaml ##\r64 ############################################################################################## 65 # tlschallenge challenge 66 ############################################################################################## 67 # Email address used for registration. 68 # 69 # Required 70 # 71 #- \u0026#34;--certificatesresolvers.tlsResolver.acme.email=/secrets/cert_contact_email\u0026#34; 72 - \u0026#34;--certificatesresolvers.tlsResolver.acme.email=contact@my-domain.com\u0026#34;\rCette adresse doit être réelle, même en environnement de test (staging).\nDéfinir le serveur de certificats TLS :\nUtilisez le serveur staging de Let\u0026rsquo;s Encrypt pour éviter de dépasser la limite de requêtes lors des tests.\n## docker-compose.prod.yaml ##\r80 # CA server to use. 81 # Uncomment the line to use Let\u0026#39;s Encrypt\u0026#39;s staging server, 82 # leave commented to go to prod. 83 # 84 # Optional 85 # Default: \u0026#34;https://acme-v02.api.letsencrypt.org/directory\u0026#34; 86 # Staging: \u0026#34;https://acme-staging-v02.api.letsencrypt.org/directory\u0026#34; 87 # 88 - \u0026#34;--certificatesresolvers.tlsResolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory\u0026#34;\rPréparer le sous-domaine du tableau de bord Traefik ::\nDans la zone DNS de votre fournisseur de domaine, ajoutez une entrée CNAME pour le tableau de bord. Exemple : si votre domaine est \u0026ldquo;mon-domaine.com\u0026rdquo; et que le DASHBOARD_PREFIX est \u0026ldquo;mon-dashboard-traefik\u0026rdquo;, vous devez créer \u0026ldquo;mon-dashboard-traefik.mon-domaine.com\u0026rdquo; en tant que CNAME pointant vers \u0026ldquo;mon-domaine.com\u0026rdquo; Lancer Traefik en production :\nDans votre terminal, d\u0026rsquo;abord placez-vous sur votre répertoire de travail ensuite tapez : docker compose -f docker-compose.yaml -f docker-compose.prod.yaml up\rImportant! Les certificats émis par les serveurs staging sont techniquement valides mais ne sont pas reconnus comme fiables par les navigateurs. Vous devrez ignorer l’avertissement NET::ERR_CERT_AUTHORITY_INVALID afin de les utiliser.\nUne fois les tests terminés, replacez l’URL du serveur de production : \u0026ldquo;https://acme-v02.api.letsencrypt.org/directory\" Tests Vérifiez que le conteneur traefik-reverse-proxy fonctionne correctement.\nAccédez au tableau de bord à : https://mon-dashboard-traefik.mon-domaine.com/dashboard/ (remplacez bien sûr par votre adresse réelle)\nSi vous avez configuré le BasicAuth, authentifiez-vous avec les username/password que vous aviez configuré précédemment\nVérifiez le fichier acme.json :\nconnectez-vous en ssh à votre serveur afin d\u0026rsquo;accéder au conteneur de votre reverse proxy : docker exec -it prod-traefik-reverse-proxy sh\rSi vous ouvrez à présent votre fichier acme.json il devrait contenir les certificats pour le domaine principal et pour le(s) sous-domaine : cat /letsencrypt/acme.json\rAnalyse supplémentaire Ici nous mettons simplement en place une redirection de toutes les requêtes http (port 80) vers https (port 443) :\n## docker-compose.local.yaml ##\r11- \u0026#34;--entryPoints.web.address=:80\u0026#34; 12- \u0026#34;--entryPoints.web.http.redirections.entryPoint.to=websecure\u0026#34; 13- \u0026#34;--entryPoints.web.http.redirections.entryPoint.scheme=https\u0026#34; 14- \u0026#34;--entryPoints.websecure.address=:443\u0026#34;\rEn particulier dans la config de la prod, on met le https comme point d\u0026rsquo;entrée par default, anisi que la configuration du provider TLS certResolver :\n## docker-compose.prod.yaml ##\r23 - \u0026#34;--entryPoints.web.address=:80\u0026#34; 24 - \u0026#34;--entryPoints.web.http.redirections.entryPoint.to=websecure\u0026#34; 25 - \u0026#34;--entryPoints.web.http.redirections.entryPoint.scheme=https\u0026#34; 26 - \u0026#34;--entryPoints.websecure.address=:443\u0026#34; 27 - \u0026#34;--entrypoints.websecure.asDefault=true\u0026#34; 28 - \u0026#34;--entrypoints.websecure.http.tls.certResolver=tlsResolver\u0026#34;\rEn local, la génération de certificats TLS est gérée par un service tiers mkcert, ici:\n## docker-compose.local.yaml ##\r38traefik-mkcert: 39 image: vishnunair/docker-mkcert 40 container_name: traefik-mkcert 41 42 environment: 43 - domain=${DOMAIN_NAME}, *.${DOMAIN_NAME} 44 volumes: 45 - ./certs/:/root/.local/share/mkcert 46 labels: 47 - \u0026#34;traefik.enable=false\u0026#34; 48 networks: 49 - my-external-network\rVous pouvez retrouver le repo du projet que j\u0026rsquo;ai emprunté ici : vishnunair/docker-mkcert Par ailleurs, étant donné que les deux conteneurs traefik-reverse-proxy et traefik-mkcert définissent un volume associé au répertoire \u0026ldquo;certs\u0026rdquo; de l\u0026rsquo;ordinateur hôte (host), le conteneur traefik-reverse-proxy peut donc lire les certificats générés par traefik-mkcert :\n## docker-compose.local.yaml ##\rtraefik-reverse-proxy: ... ... volumes: - ./certs/:/etc/certs:ro ... ... traefik-mkcert: ... ... volumes: - ./certs/:/root/.local/share/mkcert ... ...\rEn local, on définit un port supplémentaire 8080 :\n## docker-compose.local.yaml ##\r33 ports: 34 - \u0026#34;80:80\u0026#34; 35 - \u0026#34;443:443\u0026#34; 36 - \u0026#34;8080:8080\u0026#34;\rSa config étant dehors celle des entryPoints, cela nous permet d\u0026rsquo;accéder facilement au dashboard Traefik, directement en http :\n## docker-compose.local.yaml ##\r5 command: 6 - \u0026#34;--api.dashboard=true\u0026#34; 7 - \u0026#34;--api.insecure=true\u0026#34; 8 9 - \u0026#34;--serversTransport.insecureSkipVerify=true\u0026#34;\rCoté prod, il arrive que le ficher acme.json aie des soucis de permissions si on le laisse tel quel, c\u0026rsquo;est pour cela que l\u0026rsquo;on définit explicitement ses permissions lors du runtime via :\n## entrypoint.sh ##\r1#! /bin/sh 2set -e 3 4echo \u0026#34;Setting acme.json permissions 0600\u0026#34; 5touch /letsencrypt/acme.json 6chmod 600 /letsencrypt/acme.json 7chown root:root /letsencrypt 8chown root:root /letsencrypt/acme.json\rConclusion Nous avons mis en place un reverse proxy Traefik prêt à l’emploi avec génération automatique de certificats Let’s Encrypt, fonctionnant à la fois en local et sur un nom de domaine réel.\nProchaine étape : ajouter un service (conteneur Docker) ayant le même réseau externe que le notre actuel proxy, et observer la magie opérer — Traefik le détectera et le gérera automatiquement.\n","permalink":"/fr/posts/traefik/setup/","tags":[{"LinkTitle":"Traefik","RelPermalink":"/fr/tags/traefik/"},{"LinkTitle":"Reverse Proxy","RelPermalink":"/fr/tags/reverse-proxy/"},{"LinkTitle":"Docker","RelPermalink":"/fr/tags/docker/"},{"LinkTitle":"Docker Compose","RelPermalink":"/fr/tags/docker-compose/"},{"LinkTitle":"Let's Encrypt","RelPermalink":"/fr/tags/lets-encrypt/"}],"title":"Reverse Proxy Traefik Dockerisé"},{"categories":[],"content":"Bienvenue sur mon site personnel. Ici vous trouverez quelques unes de mes explorations techniques.\nJ\u0026rsquo;ai un parcours assez riche dans le monde du développement web. Ainsi en 2008 je commençais déjà à jouer avec du JAVASCRIPT et du PHP en parallèle à ma formation laquelle était en JAVA. Depuis, j\u0026rsquo;ai eu la chance, de part mes expériences directes en entreprise, ou bien via quelques expérimentations personnelles, de pouvoir jongler avec plusieurs frameworks web/mobile que ça soit coté front ou back. Ma méthode est très simple: apprendre en faisant.\nJ\u0026rsquo;ai par ailleurs eu l\u0026rsquo;opportunité de gérer des équipes restreintes de développeurs. J\u0026rsquo;ai également participé à de la gestion de projet pure à de nombreuses reprises.\nMa satisfaction vient avant tout du fait de partager mes connaissances. Aussi, si à travers mes articles j\u0026rsquo;ai pu aider ne serais-ce qu\u0026rsquo;une seule personne, ma mission est ainsi dire accomplie.\n","permalink":"/fr/about/","tags":[],"title":"A propos"}]