AI 资讯
wkhtmltopdf in Docker in 2026: musl, libssl1.1, and the ways out
Disclosure up front: I'm Vitalii, founder of PDFik , a hosted URL/HTML-to-PDF API. It shows up once near the end, clearly marked. The rest of this is the debugging guide I wish existed the last three times someone hit these errors. If you run wkhtmltopdf in containers, you have probably met at least one of these three errors: sh: /usr/local/bin/wkhtmltopdf: not found # Alpine wkhtmltox : Depends: libssl1.1 but it is not installable E: Unable to locate package wkhtmltopdf # Ubuntu 24.04 / Debian 13 All three have the same root cause: the project is archived (January 2023, repository read-only ) and the last official packages were built in May 2023 — release 0.12.6.1-3 , whose newest targets are Debian 12 (bookworm) and Ubuntu 22.04 (jammy). The distros kept moving; the binaries stopped. Here is what each error actually means, the recipe that still works in 2026, and the honest exits. Error 1: not found on Alpine — it's not about PATH The confusing part: the file is there, ls sees it, and the shell still says not found . That message comes from the kernel failing to load the binary's interpreter: official wkhtmltopdf builds link against glibc , Alpine ships musl , and the referenced dynamic loader ( /lib64/ld-linux-x86-64.so.2 ) does not exist on Alpine. ldd /usr/local/bin/wkhtmltopdf shows it immediately. There is no supported way around it on Alpine today: the distro dropped its wkhtmltopdf package years ago (nothing in current stable), and gcompat shims are a lottery with a binary this large. If the container must run wkhtmltopdf, don't build it on Alpine — that fight is not worth the ~50 MB you save. Error 2: Depends: libssl1.1 — you're installing a 2020 build on a 2023+ distro The widely-copied Dockerfiles fetch wkhtmltox_0.12.6-1.*.deb , which links OpenSSL 1.1. Debian 12, Ubuntu 22.04+ and everything after ship OpenSSL 3 and removed libssl1.1 from the archives, so the dependency is unresolvable. (Pinning an EOL base image or hand-installing an EOL libssl to wor
AI 资讯
Docker in Production: What Changes When Containers Meet Reality?
post 8: You run a container. It starts successfully. The application works. So… is it production-ready? Not necessarily. The real test of a production container isn't what happens when everything works. It's what happens when something goes wrong. What happens when the application consumes all available memory? What happens when the process crashes? What happens when the application is running, but isn't actually healthy? Where do the logs go? How do you know something is wrong before users tell you? And when the container fails, how do you find the actual cause? Running Docker in production isn't just about starting containers. It's about making them reliable, observable, manageable, and recoverable. 1. Production Starts With Boundaries A container that works perfectly on a developer's laptop can behave very differently under production load. Development often prioritizes: Speed Convenience Easy debugging Frequent changes Production prioritizes: Reliability Predictability Security Observability Recovery One of the first production questions is: What happens if this container consumes more resources than expected? That's where resource limits come in. 2. Resource Limits – Don't Let One Container Consume Everything Without appropriate resource limits, a container can consume more host resources than intended. For example: docker run \ --memory = 512m \ --cpus = 1.0 \ nginx This limits the container to: 512 MB memory 1 CPU Why does this matter? Imagine one application suddenly starts consuming several gigabytes of memory. Without appropriate limits, it could affect other workloads running on the same host. Resource limits create boundaries between workloads. But remember: A resource limit doesn't fix a memory leak. It only limits how much damage that container can cause to the host. So now we have another question: What if the container is running, but the application inside it is broken? 3. Health Checks – Running Doesn't Mean Healthy One of the most important produc
AI 资讯
How I Built a Zero-Trust Docker Sandbox for AI Coding Agents & Untrusted Repos
My vision a lightweight, permission-headache-free Docker setup for running OpenCode, uv, and untrusted Python code without risking your host OS. When contributing to unfamiliar open-source projects or letting AI coding agents (like OpenCode ) run terminal commands, there's always a slight hesitation. What if a build script touches my system Python, or a rogue command wipes host files? To solve this, I built saferun a zero-trust, disposable Docker sandbox designed specifically for Python developers and AI agent workflows on macOS and Linux. Here’s how it works, the permission nightmares I had to solve, and how you can set it up in under two minutes. The Goal I wanted a workspace that gave me: Absolute Isolation: Runtime scripts, pytest , ruff , and AI agent commands execute strictly inside a disposable Linux container. Seamless IDE Integration: Files edited inside PyCharm or VS Code on the host machine sync instantly with the container. Zero Permission Headaches: Any files generated inside the sandbox belong to my host user account—not root . Persistent Speed: Package downloads cached permanently via uv so environment startup stays millisecond-fast. Isolated Credentials: Global SSH and Git keys remain safely on the host machine. Solving the "Non-Root" Docker Nightmare The hardest part of containerized dev environments is file ownership. If you run Docker as root , any file your AI agent generates belongs to root , locking you out on your host machine. If you pass your local user ID ( -u "$(id -u):$(id -g)" ), Docker mounts non-existent directories as root:root , causing Permission Denied crashes when tools like uv try to write to cache folders. saferun solves this inside the base Dockerfile by pre-creating cache directories and granting open write permissions upfront: FROM python:3.12-slim # Install curl (needed to install OpenCode) RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ && rm -rf /var/lib/apt/lists/ * # Install uv globally RUN pip
AI 资讯
AWS EC2 Deployment — Q&A Reference
A reference guide compiled from deploying two Node.js/Docker apps to AWS EC2, covering the real issues hit and how they were fixed. 1. Getting Connected Q: How do I SSH into my EC2 instance? chmod 400 your-key.pem ssh -i your-key.pem ubuntu@YOUR_ELASTIC_IP Type yes when asked about the fingerprint the first time. Q: chmod 400 doesn't seem to work / I get "bad permissions" / "Permission denied (publickey)" This happens when your .pem key sits on a Windows drive mounted into WSL (e.g. /mnt/c/Users/you/Downloads ). NTFS doesn't honor Linux permission bits properly. Fix: copy the key into WSL's native filesystem first. mkdir -p ~/.ssh cp "/mnt/c/Users/you/Downloads/your-key.pem" ~/.ssh/your-key.pem chmod 400 ~/.ssh/your-key.pem ssh -i ~/.ssh/your-key.pem ubuntu@YOUR_ELASTIC_IP Q: My key filename has spaces in it — how do I reference it? Wrap it in quotes: ssh -i "Terminal Key Pair.pem" ubuntu@YOUR_ELASTIC_IP Q: How do I know which actual instance/IP I'm connected to? TOKEN = $( curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ) curl -s -H "X-aws-ec2-metadata-token: $TOKEN " http://169.254.169.254/latest/meta-data/instance-id curl -s -H "X-aws-ec2-metadata-token: $TOKEN " http://169.254.169.254/latest/meta-data/public-ipv4 Compare this to what the AWS Console shows for your instance — it's easy to accidentally SSH into an old instance if an Elastic IP got reassigned. 2. Domain Name / HTTPS Without Buying a Domain Q: I don't want to buy a domain — can I still get real HTTPS? Yes — use sslip.io . Any hostname like YOUR_IP.sslip.io automatically resolves to that IP with zero signup. Let's Encrypt (via Certbot) will issue a real, trusted certificate for it just like a paid domain. Q: Why can't I just use the raw IP with HTTP? Clerk (auth) and Razorpay (payments) both require HTTPS with a real hostname in production/live mode. Plain http://ip will not work with either. Q: I later bought a real domain — how do I switch o
AI 资讯
Stop Copy-Pasting Parts in Docker Compose
Imagine you have a complex microservice. For local development, you need it connected to a message queue, a telemetry collector, and a database. But for your E2E testing, you need a slightly modified version (different env vars, an extra mock dependency, maybe a different port). Most engineers solve this by maintaining two massive, almost-identical YAML files. It is a nightmare to sync changes. Or they simply do this: $ docker compose -f compose.yml -f e2e-compose.yml up --build -d I do NOT like neither of them. Instead use YAML Anchors (&) , Merge Keys (<<:) , and Compose Profiles to create a single, DRY (Don't Repeat Yourself) configuration file. # ------------------------------------------------------------ # 1. REUSABLE BUILDING BLOCKS (Anchors) # ------------------------------------------------------------ x-backend-depends-on : &backend-depends-on message-queue : condition : service_healthy telemetry-collector : condition : service_started x-backend-config : &backend-config build : . user : " 1000:1000" ports : - " 3000:$PORT" env_file : - .env healthcheck : test : [ " CMD" , " curl" , " -f" , " http://localhost:${PORT:-3000}/health" ] interval : 5s timeout : 5s retries : 12 start_period : 10s depends_on : *app-depends-on # ------------------------------------------------------------ # 2. SERVICES # ------------------------------------------------------------ services : # --- Production / Dev Service --- backend : << : *backend-config profiles : [ " dev" ] # --- E2E Test Variant --- backend-e2e : << : *app-config profiles : [ " e2e" ] # Only starts when explicitly called environment : # Override specific ENV vars for testing RETRY_DELAY_MS : " 100" TIMEOUT_MS : " 200" depends_on : << : *app-depends-on # Inherit all base dependencies e2e-fixture : # ADD an extra dependency for testing condition : service_healthy # ... So now how this changes your workflow: Local: docker compose --profile dev up starts only backend + services in default/dev profile. E2E testing:
AI 资讯
Deploying Multiple Python Bots to a Single Railway Container
A tutorial for running two or more python bots on Railway inside one container and one service, with independent crash recovery for each. Deploying Multiple Python Bots to a Single Railway Container If you're running more than one Python bot — say, a Telegram ingestion bot and a Discord notification bot that share a database — deploying each as its own Railway service means double the hosting cost and double the configuration for something that's logically one unit. This tutorial covers deploying both bots inside a single Railway container, with each one still getting fully independent crash recovery. Table of Contents Why Two Services Is Usually Overkill The Naive Fix and Why It Falls Short Step 1: Install StayPresent Step 2: Structure Your Project Step 3: Configure Multiple Bots in One Entry Point Step 4: Read Railway's Assigned Port Step 5: Deploy as a Single Railway Service Verifying Both Bots Are Running FAQs Conclusion Why Two Services Is Usually Overkill Railway (like most PaaS platforms) charges per service, and each service needs its own configuration, environment variables, and deployment pipeline. If two bots are closely related — sharing a database, a queue, or just conceptually belonging to the same project — running them as two separate Railway services duplicates all of that for no real benefit. The Naive Fix and Why It Falls Short A common first instinct is a shell script: python telegram_bot.py & python discord_bot.py & wait This runs both, but there's no real process supervision here — if telegram_bot.py crashes, nothing restarts it, and you still haven't solved Railway's HTTP port requirement, since neither script opens one. Step 1: Install StayPresent pip install staypresent[prod] # requirements.txt staypresent[prod] Step 2: Structure Your Project project/ ├── main.py ├── telegram_bot.py ├── discord_bot.py ├── requirements.txt Both bot scripts stay exactly as they are — nothing about their internal logic needs to change. Step 3: Configure Multipl
AI 资讯
Docker Launches Fully Rebuilt Virtualization Layer to Boost Performance and Improve Dev Experience
Docker VMM (virtual machine monitor) is Docker's new, first-party virtualization layer for Docker Desktop, replacing third-party virtualization components with an engine that Docker can directly control and optimize specifically for container workloads. The public beta launched with Docker Desktop 4.86 for Mac and Windows. By Sergio De Simone
AI 资讯
Docker Compose Isn't What I Thought It Was
post 7: A practical guide to understanding Docker Compose—what it is, how it works, and the misconceptions that catch most beginners. You've mastered single containers. Now it's time to build a real application. A frontend. A backend. A database. A Redis cache. Suddenly you're juggling multiple docker run commands. Ports. Networks. Volumes. Environment variables. Chaos. Then someone says: "Just use Docker Compose." It works beautifully. But here's the twist most people never realize… Why Docker Compose Exists Imagine starting an application like this: Frontend Backend PostgreSQL Redis Running each container manually quickly becomes repetitive and error-prone. Docker Compose lets you describe your entire application in a single YAML file and start everything with one command. Instead of remembering dozens of commands, you define your infrastructure once. What Docker Compose Actually Is Docker Compose is not a container orchestrator . Docker Compose is a tool that reads your Compose YAML file and uses the Docker Engine to create and manage the resources defined in it.” Modern Docker uses Compose V2 , which runs as: docker compose instead of the older: docker-compose Compose runs only when you execute a command. It creates the required Docker resources, starts the containers, and then exits. This makes it ideal for development, testing, and single-host deployments , but it doesn't provide orchestration features like automatic scheduling, self-healing, or multi-node management. A Simple docker-compose.yml services : web : build : . ports : - " 8080:80" environment : - DB_HOST=db depends_on : - db db : image : postgres:15 volumes : - postgres_data:/var/lib/postgresql/data redis : image : redis:alpine volumes : postgres_data : YAML Quick Reference Key Purpose services Defines containers (web, db, redis) build Builds an image from a Dockerfile image Uses an existing image from a registry ports Maps host ports to container ports environment Sets environment variables depend
AI 资讯
CI/CD Pipelines That Actually Work: Lessons from The Matrix
The Quest Begins (The “Why”) Honestly, I used to stare at my CI/CD yaml files like they were ancient runes. Every push felt like a gamble: “Will the build pass this time?” I’d spend Friday nights hunting down a missing node_modules cache in Jenkins, only to realize the agent had run out of disk space because I’d forgotten to add a cleanup step. The pain was real, and the feedback loop was slower than a dial‑up modem. I kept asking myself: Why does this feel like wrestling a dragon every time I want to ship a feature? The answer was simple—I hadn’t yet found a pipeline that just worked out of the box. I wanted something that gave me confidence, not anxiety. So I embarked on a quest to compare the three big contenders: GitHub Actions, GitLab CI, and good ol’ Jenkins. Spoiler: the treasure wasn’t in the tool itself, but in how you shape the pipeline around your team’s flow. The Revelation (The Insight) The big “aha!” moment came when I stopped treating CI/CD as a one‑size‑fits‑all script and started seeing it as a contract between my code and my environment. The contract says: Every commit gets a clean slate. Dependencies are restored, not guessed. Tests run in parallel, not sequentially. Artifacts are published only if the gate passes. When I wrote that contract down, the yaml stopped looking like magic incantations and started looking like a checklist. The tools differ in syntax, but the underlying principles are the same. Here’s the secret: cache wisely, fail fast, and keep the pipeline short enough to give you feedback before you’ve even finished your coffee. Wielding the Power (Code & Examples) Below are three pipelines—one for each platform—that embody the contract above. I’ll first show a “struggle” version (the common pitfalls) and then the victorious version. 1. GitHub Actions – The Struggle name : CI on : [ push , pull_request ] jobs : build : runs-on : ubuntu-latest steps : - uses : actions/checkout@v3 - name : Install deps run : npm install # <-- no cache,
AI 资讯
Docker avançado - multi-stage builds, segurança e CI/CD
1. Retomando: da aplicação funcionando ao container pronto para produção Esta série cobriu, até aqui, o suficiente para desenvolver com Docker no dia a dia: conceitos fundamentais, comandos essenciais, Dockerfiles eficientes, rede, volumes e Compose para orquestrar múltiplos serviços. Este último artigo fecha a lacuna entre "funciona no meu Compose local" e "pronto para rodar em produção": imagens menores via multi-stage builds, segurança básica e não negociável, e como tudo isso se integra a um pipeline de CI/CD. 2. O problema que multi-stage builds resolve Compilar ou empacotar uma aplicação frequentemente exige ferramentas que a aplicação não precisa em tempo de execução : compiladores, headers de desenvolvimento, o próprio código-fonte antes de ser transpilado/buildado. Um Dockerfile ingênuo carrega tudo isso para a imagem final: # Ruim: ferramentas de build viajam junto para produção FROM node:20 WORKDIR /app COPY . . RUN npm install && npm run build CMD ["node", "dist/server.js"] Essa imagem inclui o npm , todo o node_modules (incluindo dependências de desenvolvimento), o código-fonte original e as ferramentas de build — frequentemente centenas de MBs de peso morto que nunca são usados depois que npm run build termina, e que ainda aumentam a superfície de ataque da imagem (mais binários, mais coisa que pode ter vulnerabilidade). Multi-stage builds resolvem isso permitindo múltiplos blocos FROM no mesmo Dockerfile, onde estágios posteriores copiam seletivamente apenas o que precisam dos anteriores — o restante do estágio de build simplesmente não existe na imagem final: # Estágio 1: build, com todas as ferramentas necessárias FROM node:20 AS build WORKDIR /app COPY package*.json . RUN npm ci COPY . . RUN npm run build # Estágio 2: produção, só com o resultado do build FROM node:20-slim WORKDIR /app COPY --from=build /app/dist ./dist COPY --from=build /app/node_modules ./node_modules COPY package*.json . CMD ["node", "dist/server.js"] A imagem final não contém o
AI 资讯
Docker Compose - orquestrando múltiplos containers
1. Retomando: do docker run repetido a um arquivo único No artigo anterior, subir uma API e um Postgres conectados exigiu dois comandos docker run longos, com flags de rede, volume e variáveis de ambiente para lembrar (e digitar) toda vez. Em um projeto real, com mais serviços — cache, fila, worker em background — isso rapidamente vira inviável de manter na cabeça ou em um script solto. O Docker Compose resolve isso descrevendo toda a aplicação multi-container em um único arquivo declarativo, versionado junto com o código. 2. O arquivo compose.yaml Compose lê um arquivo YAML (por convenção compose.yaml , ou o nome legado docker-compose.yml , ainda amplamente usado) descrevendo serviços (cada um vira um ou mais containers), redes e volumes: # compose.yaml services : api : build : . ports : - " 8000:8000" environment : DATABASE_URL : postgresql://postgres:segredo@banco:5432/postgres depends_on : - banco banco : image : postgres:16 environment : POSTGRES_PASSWORD : segredo volumes : - pg-dados:/var/lib/postgresql/data volumes : pg-dados : Isso substitui inteiramente os dois docker run do artigo anterior. Uma diferença importante já aparece aqui: por padrão, Compose cria uma rede própria para o projeto e conecta todos os serviços a ela automaticamente — não é preciso um docker network create manual, nem declarar --network em cada serviço. Cada serviço já é acessível pelos demais pelo nome declarado em services: (aqui, banco resolve para o container do Postgres), exatamente como as redes definidas pelo usuário do artigo anterior. 3. Comandos essenciais do Compose docker compose up -d # sobe todos os serviços em segundo plano docker compose ps # lista os containers do projeto e seu status docker compose logs -f api # segue os logs de um serviço específico docker compose logs -f # segue os logs de todos os serviços, intercalados docker compose exec api bash # abre um shell dentro do container de um serviço docker compose stop # para os containers sem removê-los docker comp
开发者
Cómo solucionar `docker run` con `Exited (1)` en Raspberry Pi
Cómo solucionar docker run con Exited (1) en Raspberry Pi ¿Por qué ocurre este error? El código de salida 1 indica que el proceso principal del contenedor terminó con un error genérico. En Raspberry Pi, los casos más comunes son: Arquitectura incompatible : La imagen fue construida para amd64 (x86_64), pero Raspberry Pi usa arm32v7 o arm64v8 . Falta de binarios compatibles : El ENTRYPOINT o CMD del contenedor intenta ejecutar un binario compilado para otra arquitectura. Problemas de permisos o dependencias faltantes en el entorno embebido (especialmente en Raspberry Pi OS Lite sin GUI). Uso incorrecto de --net=host : En algunas versiones de Docker en Raspberry Pi, el flag --net=host puede causar fallos si el sistema no lo soporta correctamente. 🔍 Nota crítica : En tu comando original docker run --net = host -d -t myimage , hay un error de sintaxis: --net = host tiene espacios alrededor del = . Docker lo interpreta como un nombre de red literal " = host" , lo que probablemente falla. Pasos para solucionarlo Paso 1: Corrige la sintaxis del comando # ❌ Incorrecto (con espacios en `--net`) docker run --net = host -d -t myimage # ✅ Correcto (sin espacios) docker run --net host -d -t myimage ⚠️ Importante : En Docker CLI, los flags con valores no deben tener espacios entre el = . Usa --net=host o --net host , pero nunca --net = host . Paso 2: Verifica la arquitectura de la imagen Ejecuta en tu Raspberry Pi: docker inspect myimage --format '{{.Architecture}}' Si el resultado es amd64 , la imagen no es compatible con Raspberry Pi . Solución: Reconstruir la imagen para ARM Si tienes el Dockerfile , usa multi-arch build: # Al inicio del Dockerfile (antes de FROM) # syntax=docker/dockerfile:1 FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder ... O construye explícitamente para ARM: # En tu máquina de desarrollo (x86_64) docker buildx create --use docker buildx build --platform linux/arm/v7 -t myimage:armv7 . --push # o para Pi 4 (64-bit): docker buildx build --platf
AI 资讯
Kubernetes for Beginners: From Local to Production – May the Pods Be With You
The Quest Begins (The "Why") I remember the first time I tried to take a weekend side‑project from my laptop to something that felt “real”. I had a cute Express API that talked to Postman, a PostgreSQL container spun up with docker-compose up , and a React front‑end that lived in its own dev server. Everything worked beautifully … until I hit Ctrl+C on my laptop and the whole thing vanished. I needed a way to say, “Hey, keep this running even if I close my laptop, and if something crashes, bring it back up automatically.” I started poking at Docker Swarm, then Nomad, but the docs felt like reading ancient runes. That’s when a coworker slid over a Slack message: “Just try a Kind cluster. It’s K8s locally, and you’ll see why everyone talks about it.” Spoiler: it felt like discovering the secret level in a classic arcade game. Suddenly I could describe what I wanted my system to look like, and the cluster would make it happen — no more babysitting containers. The Revelation (The Insight) Kubernetes isn’t a mystical black box; it’s a declarative orchestrator . You tell it the desired state of your application (how many replicas, which image, what ports to expose) and it works relentlessly to match reality to that state. If a pod dies, Kubernetes spins up a new one. If you ask for three replicas and only two are running, it creates the missing pod. If you update the image tag, it rolls out the change pod‑by‑pod, keeping traffic flowing. Think of it like the save‑game system in a RPG: you define the story you want to experience, and the engine handles the gritty details of loading, saving, and recovering from crashes. The core objects you’ll meet early on are: Pod – the smallest deployable unit (one or more tightly coupled containers). Deployment – manages a set of identical pods, handles updates and rollbacks. Service – a stable network endpoint that load‑balances traffic to a set of pods. Ingress (optional) – exposes HTTP/HTTPS routes from outside the cluster to service
AI 资讯
Docker - redes e volumes na prática
1. Retomando: de imagens bem construídas a containers que conversam entre si Os artigos anteriores desta série cobriram como criar imagens eficientes e rodar containers isolados. Mas uma aplicação real raramente é um único container: normalmente há uma API, um banco de dados, um cache, talvez uma fila de mensagens — cada um em seu próprio container, precisando se comunicar. E containers, por padrão, são efêmeros: qualquer dado escrito dentro deles some quando são removidos. Este artigo cobre as duas peças que resolvem isso: redes (comunicação entre containers) e volumes (persistência de dados). 2. O problema do isolamento de rede por padrão Cada container recebe seu próprio namespace de rede, isolado dos demais e do host. Isso é uma característica de segurança, não um bug — mas significa que dois containers rodados de forma independente não conseguem se encontrar automaticamente: docker run -d --name api minha-api docker run -d --name banco postgres De dentro do container api , tentar acessar banco por esse nome simplesmente falha — cada container, isolado, só enxerga localhost como a si mesmo. A solução do Docker para isso é criar uma rede e conectar ambos os containers a ela. 3. Redes definidas pelo usuário (User-Defined Networks) docker network create minha-rede docker run -d --name banco --network minha-rede postgres docker run -d --name api --network minha-rede minha-api A partir daqui, dentro do container api , o hostname banco resolve automaticamente para o IP do container banco — o Docker roda um DNS interno para qualquer rede definida pelo usuário, resolvendo containers pelo nome (ou pelo alias definido com --network-alias , se houver mais de um). Isso é o motivo pelo qual strings de conexão em aplicações containerizadas costumam usar o nome do serviço em vez de um IP fixo: DATABASE_URL = postgresql :// usuario : senha @ banco : 5432 / meudb Comandos úteis para inspecionar redes: docker network ls # lista todas as redes docker network inspect minha-rede # d
AI 资讯
Docker Networking & Volumes: Connecting Containers and Persisting Data
Learn how containers communicate with each other and how to keep data alive even after containers are removed. Modern applications rarely run as a single container. A typical application might include a web application, a database, a cache layer, and background workers. For these services to work together, containers need a reliable way to communicate and share data. In this article, we'll learn: How Docker networking works How containers discover each other Docker network drivers Persistent storage with Docker volumes Essential networking and volume commands A real-world multi-container example By the end, we'll understand two of the most important concepts in Docker: networking and data persistence . Why Docker Networking Matters Every container runs inside its own isolated network namespace. This isolation improves security and prevents conflicts, but it also creates an important challenge: If containers are isolated, how does a web application connect to a database? Imagine a web application running inside one container and MongoDB running inside another. Without networking, they cannot communicate. Docker solves this problem using Docker Networks . A Docker network allows containers to communicate with each other while remaining isolated from unrelated containers. Web App Container | v Docker Network | v Database Container Without a shared network, containers cannot easily find or communicate with each other. Docker Network Drivers Docker supports several network drivers, but most developers primarily use three. Bridge Network A bridge network creates a private virtual network on the Docker host. Containers connected to the same bridge network can communicate with each other securely. Create a custom bridge network: docker network create my-app-network Benefits of bridge networks: Container-to-container communication Isolation from other applications Built-in DNS resolution Easy management For most Docker projects, a user-defined bridge network is the recommend
AI 资讯
Dockerfile na prática - camadas, cache de build e boas práticas
1. Retomando: do Dockerfile mínimo a um Dockerfile de verdade Na segunda parte desta série, um Dockerfile de poucas linhas já foi suficiente para empacotar uma aplicação Python. Isso funciona, mas um Dockerfile escrito sem pensar em camadas e cache de build gera imagens maiores do que precisam ser e builds que demoram muito mais do que deveriam a cada mudança pequena no código. Este artigo aprofunda como o Docker constrói uma imagem por dentro, e como escrever um Dockerfile que tira proveito disso. 2. Como funcionam as camadas (layers) Cada instrução de um Dockerfile ( FROM , RUN , COPY , ADD ) que modifica o sistema de arquivos gera uma camada — um diff read-only armazenado separadamente e empilhado sobre as anteriores. A imagem final é simplesmente a soma de todas essas camadas, e o container em execução adiciona uma camada gravável no topo (union filesystem). Container (camada gravável) ────────────────────────── Camada 4: COPY . . Camada 3: RUN pip install -r requirements.txt Camada 2: COPY requirements.txt . Camada 1: FROM python:3.12-slim Duas consequências práticas importantes: Camadas são reaproveitadas entre imagens. Se duas imagens diferentes compartilham as mesmas primeiras instruções (por exemplo, a mesma FROM e o mesmo RUN apt-get install ), o Docker armazena essa camada uma única vez em disco, mesmo que várias imagens a usem. Camadas são cacheadas entre builds. Ao rodar docker build de novo, o Docker verifica cada instrução, na ordem: se a instrução e seus arquivos de entrada não mudaram desde o último build, ele reaproveita a camada já construída em vez de refazer o trabalho. Isso é a base de todo o próximo tópico. 3. Cache de build: ordenar o Dockerfile por frequência de mudança O cache de build é invalidado a partir do primeiro ponto de mudança : se a instrução N mudou (ou um arquivo que ela copia mudou), toda camada a partir de N é reconstruída — mesmo que as instruções seguintes sejam idênticas ao build anterior. Isso significa que a ordem das ins
开发者
Reviving Open Source Giants: How I Brought Weave Scope Back with Multi-Platform Docker Support in One Afternoon Using Antigravity
How to rescue abandoned open-source projects, modernize build systems, and generate multi-architecture Docker images (x86_64, ARM64) in a single afternoon with Antigravity.
AI 资讯
Docker no dia a dia - comandos essenciais e primeiros containers reais
1. Retomando: de imagens a containers em execução Na primeira parte desta série vimos o que é o Docker, o problema que ele resolve e os três conceitos fundamentais — imagens, containers e registries. Agora que a base teórica está posta, o foco deste artigo é prático: os comandos que efetivamente viram hábito no uso diário — run , exec , logs , ps , build — aplicados a containers reais, não só ao hello-world . 2. docker run além do básico O artigo anterior já usou docker run para subir um Nginx. Vale conhecer as flags que aparecem o tempo todo: # Modo interativo, útil para explorar uma imagem manualmente docker run -it ubuntu bash # Variáveis de ambiente docker run -e POSTGRES_PASSWORD = segredo -d postgres # Montar um diretório do host dentro do container (volume bind mount) docker run -v $( pwd ) /dados:/dados -d minha-imagem # Remover o container automaticamente quando ele parar docker run --rm -it python:3.12 python3 # Limitar recursos docker run --memory = 512m --cpus = 1 minha-imagem -it combina -i (interativo, mantém STDIN aberto) com -t (aloca um pseudo-terminal) — é o par de flags para "entrar" em um container e usar um shell como se fosse uma máquina normal. --rm evita acumular containers parados no disco depois de testes rápidos e descartáveis — sem ela, cada docker run deixa um container parado para trás até ser removido manualmente. -e define variáveis de ambiente; imagens oficiais como a do Postgres costumam documentar quais variáveis elas esperam (usuário, senha, nome do banco inicial). 3. Inspecionando o que está rodando O comando mais usado para ter uma visão geral do que o Docker está gerenciando na máquina: docker ps # containers em execução docker ps -a # todos, incluindo parados docker ps -q # só os ids (útil em scripts) Para investigar um container específico mais a fundo: docker inspect meu-container # todos os metadados em JSON: rede, volumes, config docker top meu-container # processos rodando dentro do container docker stats # uso de CPU/mem
AI 资讯
Kubernetes and Docker
Docker and Kubernetes are two of the most consequential infrastructure technologies of the last decade. They changed how software is built, packaged, and deployed. They are also two technologies that most engineers use before they understand, which creates gaps in knowledge that show up at the worst times: a production outage, a security incident, a performance problem you cannot diagnose. This guide builds understanding from the ground up. Every concept is introduced with the problem it solves. You will understand why containers exist before you understand what they are. You will understand why Kubernetes exists before you understand how it works. By the end, you will know not just how to run these technologies but how to reason about them. Table of Contents The Problem Containers Solve - Why Docker Exists Docker Internals - What a Container Actually Is Images - Building Portable Application Packages Dockerfile - Writing Reproducible Builds Docker Networking - Container Communication Docker Volumes - Managing State Docker Compose - Multi-Container Applications The Problem Kubernetes Solves - Why Orchestration Exists Kubernetes Architecture - The Control Plane and Data Plane Core Kubernetes Objects - Pods, Deployments, Services, ConfigMaps, Secrets Namespaces and RBAC - Multi-Tenancy and Access Control Storage in Kubernetes - Persistent Volumes Ingress - Routing External Traffic Helm - Package Management for Kubernetes Service Mesh - Istio and Advanced Traffic Management AWS Container Services - ECS and EKS Real Architecture Patterns The Problem Containers Solve - Why Docker Exists The Classic Failure Mode A developer builds an application on their MacBook. It works. They hand it to the QA team. It does not work. They hand it to the operations team to deploy to production. It works differently than in QA. "It works on my machine" is not a joke. It is a description of a real, chronic infrastructure problem. The application depends on: A specific version of Python, No
AI 资讯
Docker - O Que É, Para Que Serve e Conceitos Iniciais
1. O Problema que o Docker Resolve "Na minha máquina funciona." Poucas frases resumem tão bem um problema que atormentou (e ainda atormenta) times de desenvolvimento: um código que roda perfeitamente no notebook do desenvolvedor, mas quebra no servidor de produção — porque a versão do Python é outra, uma biblioteca do sistema está faltando, uma variável de ambiente não foi configurada, ou o sistema operacional simplesmente se comporta de forma diferente. O Docker resolve exatamente isso: ele empacota uma aplicação junto com tudo que ela precisa para rodar — código, dependências, bibliotecas do sistema, variáveis de ambiente, configuração — em uma unidade isolada e portátil chamada container . Essa unidade roda da mesma forma em qualquer lugar que tenha o Docker instalado: no notebook do desenvolvedor, no servidor de CI, ou em produção. Esta é a primeira parte de uma série que vai do zero ao avançado em Docker: hoje o foco é entender o problema que ele resolve, os conceitos fundamentais e como eles se encaixam. 2. Containers vs Máquinas Virtuais A comparação mais comum ao explicar Docker é com máquinas virtuais (VMs), porque ambos resolvem um problema parecido — isolar e empacotar aplicações — mas de formas muito diferentes. Uma máquina virtual virtualiza o hardware inteiro: cada VM roda seu próprio sistema operacional completo (kernel incluso), gerenciado por um hypervisor. Isso garante isolamento forte, mas tem um custo alto: cada VM consome centenas de MBs a alguns GBs de disco e memória só para o SO, e leva de dezenas de segundos a minutos para inicializar. Um container , por outro lado, virtualiza no nível do sistema operacional: todos os containers em uma máquina compartilham o mesmo kernel do host, mas cada um enxerga seu próprio sistema de arquivos, processos e rede isolados — usando recursos do kernel Linux como namespaces (isolamento de visão) e cgroups (limites de CPU/memória). O resultado é que containers são muito mais leves: alguns MBs a poucas centenas