AI 资讯
10 Essential Tools I Actually Use to Keep My Side Projects From Falling Over
Docker management, monitoring that goes deeper than a green dot, backups I have actually restored, and everything else that showed up once deploying stopped being the hard part. Moving off Vercel solved exactly one problem: deploying. Everything else I used to get for free, quietly, as part of the platform, I now had to go find and wire up myself. A month into running my own server, I had a list of ten tools taped to the inside of my head, each one solving a problem I did not know I had until it happened to me at a bad time. This is that list, in the order I actually needed them, with the mistake or the moment that made me install each one. I lean JS and Rust wherever I can, partly out of preference and partly because those are the tools that keep pace with how fast the rest of my stack moves. A couple of these are not JS or Rust at all, and I kept them anyway because they were simply the best tool for the job. 1. Dokploy, for everything I wrote about yesterday This is the one I already spent an entire post on, so I will keep it short here. Push to main, Dokploy builds the container, Traefik points a domain at it, done. Four apps running on one $24 droplet, and adding a fifth would not move the bill. If you deploy anything with Docker and are still doing it over SSH, start here. Everything else on this list assumes you already have a platform under you, not just a server. 2. Neon, for the database half of preview environments The first crack after Dokploy was previews. Dokploy gives every pull request its own preview URL, which is one of the nicest things about the whole setup, right up until every preview hits the same production database. I corrupted a batch of test data twice before I noticed what was happening. Neon branches Postgres the way git branches code, copy-on-write, so a preview PR gets its own preview database that costs almost nothing until it actually diverges from main. The storage engine underneath is written in Rust, and it quietly closed the othe
AI 资讯
The home server I finally stopped turning off
The most useful thing my home server taught me was not how to install another Docker container. It was how quickly a problem stops belonging to one tidy layer. A service can be running while DNS is wrong. Plex can work while the machine doing the transcoding cannot reach the storage. A reverse proxy can be configured correctly while the network around it is a mess. When it is your own server and you actually want to use it, those boundaries become your problem. That is very different from the way many application-focused software-engineering jobs feel. You can spend years building applications without having to join Linux, storage, DNS, HTTPS and networking together yourself. The experiments that kept getting turned off Around the start of 2020, I got a Raspberry Pi and repeatedly installed Raspbian or Debian on it. I would add Sonarr, Radarr, maybe Prowlarr, a torrent client and Plex. Sometimes Pi-hole joined them. There was no reverse proxy and I was not putting my own domains behind it. It was primitive, and I learnt something each time, but it never stuck, right? I would decide to play with it and eventually turn it off again. The Pi proved that I could run these services. It did not give me infrastructure I depended on. That changed in summer 2024. I had an old i5 desktop lying around, knew it worked and could connect drives to it easily. Why the hell not? I installed OpenMediaVault and spent the next two or three months building the setup out. Docker-managed services were joined by Traefik as a reverse proxy, Tailscale , proper DNS and network sharing. The useful result was a repeatable path for a new service. I could put it behind HTTPS and decide whether it should be public or only reachable inside my network. The machine was no longer an experiment waiting to be unplugged. A second machine made the lessons real I also bought a separate OptiPlex with 4 GB of RAM and installed Debian. Its main job was Plex Pass transcoding, reading media over the network from
AI 资讯
Why Serverless Engineers Already Understand Containers
The outage that teaches you deployment A service passes every test locally. It fails in staging because the API calls localhost:5432 for Postgres — but Postgres is in another container, reachable only as db:5432 . This is not a Docker problem. It is a boundary problem: your code assumed an environment it does not own. Engineers who have shipped on AWS Lambda already avoid a class of these mistakes. They never SSH into a function to hot-fix. They inject config at deploy time. They treat each invocation as disposable. Containers reward the same discipline with different vocabulary. This article maps what transfers, what breaks, and what I require before any Python backend goes to production in a container. What serverless already taught you Immutable deployments Lambda versions are replaced, not patched. Container images work the same way: build a new image, roll out, roll back by tag. If your incident runbook includes "edit files inside the running box," you have a design problem. Configuration at runtime Secrets belong in Secrets Manager or injected env vars — not in source control, not in the image layer cache. Docker does not change the rule; it changes where you mount the values. Single responsibility per unit One Lambda, one job. One container, one main process. Compose and Kubernetes add orchestration; they do not remove the rule. Cold start awareness Slim packages on Lambda map to slim base images ( python:3.12-slim , multi-stage builds). Startup time affects autoscaling and health-check windows the same way cold starts affect user-facing latency. If you understand why a Lambda deployment package should stay small, you understand why a 2 GB container image is a liability. Where the mental model breaks 1. Network identity Inside Compose or Kubernetes, localhost is the container itself. Services discover each other by DNS name ( api , db , redis ). This is the most common first-production failure I see in teams moving from bare metal or single-host deploys. 2. P
AI 资讯
Very Basic Docker Commands Cheat Sheet
If you ever needed a quick list of Docker commands, here you go.. 1. Check that Docker is installed docker --version Shows the installed Docker version. 2. Run your first container docker run hello-world Pulls the official test image (if needed) and runs it. You should see a “Hello from Docker!” message. 3. See running containers docker ps Lists containers that are currently running. Use docker ps -a to also show stopped ones. 4. See downloaded images docker images Shows every image on your machine (name, tag, size, ID). 5. Stop a running container docker stop CONTAINER_ID Gracefully stops a container. Get the ID from docker ps . 6. Remove a stopped container docker rm CONTAINER_ID Deletes a container that is already stopped. 7. Force stop and remove docker rm -f CONTAINER_ID Force-stops the container (if it’s still running) and removes it in one step.
AI 资讯
Running Local LLMs with RamaLama and Docker on a Mac: A Hands-On Guide
RamaLama runs large language models as OCI containers, so a single command ( ramalama run smollm:135m ) pulls a model and starts talking to it, with no Python environment to babysit. I spent an afternoon putting it through its paces on an Apple Silicon Mac (Apple M4 Pro, 48 GB RAM, macOS 26.6) with Docker 29.4 provided by OrbStack. This guide is what I actually saw: the install, the first model, an OpenAI-compatible server, and the one macOS-specific catch that isn't obvious from the docs. Every command and number below is from that run, on RamaLama 0.24.0. What is RamaLama? RamaLama is an open-source CLI from the container-tooling community that treats models like container images. Instead of assembling an inference stack yourself, it pulls a hardened OCI image containing llama.cpp (or vLLM/MLX) plus your chosen model and runs it with Podman or Docker. If you've used Ollama the ergonomics feel familiar ( run , serve , list , pull ), but the runtime and model live inside containers you can inspect and sign, and weights come straight from Hugging Face, Ollama, or any OCI registry. Installing RamaLama on macOS With Homebrew it's one command: brew install ramalama That pulled RamaLama 0.24.0 and, notably, its own copy of llama.cpp , ggml , and libomp as dependencies. Hold onto that detail; it matters for GPU acceleration later. Confirm the install: ramalama version # ramalama version 0.24.0 You also need a container engine running. I used Docker through OrbStack; Podman works too and is RamaLama's default on Linux. Running your first model The headline command: ramalama run smollm:135m "In one sentence, what is a Linux container?" Passing a prompt as an argument gives you one-shot output instead of dropping into a chat REPL. On first run this pulled the RamaLama container image, downloaded the model, and answered. smollm:135m resolves to hf://HuggingFaceTB/smollm-135M-instruct-v0.2-Q8_0-GGUF , a 138 MB, 8-bit quantized GGUF from Hugging Face. First-run wall-clock was 2
AI 资讯
The Docker Handbook: From Zero to Production-Ready Containers
Docker has become an essential tool for developers, DevOps engineers, and anyone deploying applications today. It solves the age-old problem of “it works on my machine” by packaging an application with everything it needs into a lightweight, isolated unit called a container. This guide takes you from absolute beginner to confidently building and running real‑world applications with Docker. 1. Why Docker Exists (The Problem) Before Docker: “It works on my machine” is the daily mantra 😵 Different OS → different bugs, different dependency versions Onboarding a new developer takes hours (Node, DB, caches, environment variables…) Servers are hand‑configured snowflakes, impossible to reproduce exactly Docker solves this: 👉 It packages your app plus everything it needs into a lightweight, isolated unit called a container . That container runs identically everywhere : Your laptop A teammate’s machine A CI/CD pipeline A production server in the cloud 2. What is Docker? Docker is a platform that lets you: Define application environments as code ( Dockerfile ) Build images from those definitions Run containers from those images Share images via a public registry ( Docker Hub ) Simple analogy: Docker = Lunch box 🍱 Your app + dependencies = the food inside Container = the sealed box you can carry anywhere, and when you open it the meal is exactly the same 3. Key Concepts (Must Know First) 📦 Image A blueprint of your application environment. It contains the OS files, dependencies, code, and configuration needed to run your app. Example images: node:18-alpine – Node.js on a tiny Alpine Linux postgres:15 – PostgreSQL database server nginx – a fast web server Think: “Class in OOP” 🚀 Container A running instance of an image . You can have multiple containers from the same image, each isolated from the others. Think: “Object created from a class” 🧱 Dockerfile A text file that defines how to build an image . It lists step‑by‑step instructions, like a recipe. Example: FROM node:18 WORKD
AI 资讯
How Many AI Avatars Can One GPU Handle? Real-World Test Reveals 4 Avatars at ¥7,600 Each per Month
📝 Originally published (in Japanese) at forge.workstyle.tech . Building an Unmanned System for 3D Avatar Live Streaming We're developing an unmanned system where 3D avatars automatically handle live streaming. The system boots up a cloud GPU pod at the scheduled start time, the renderer assembles and streams the video, and then the pod is discarded when the segment ends. Since there's no human oversight, three factors directly impact the success of the business and service quality: "how many avatars can run simultaneously," "how the system recovers from failures," and "how quickly it starts up." These questions couldn't be answered through estimates alone. Renting a GPU for a few hours costs only a few hundred yen. In this article, we'll share three stories of how we measured and designed the system, following the structure of "stumbling block → cause → solution." Capacity : How many avatars can run on a single GPU? The answer is 4, at a monthly cost of ¥7,600 per avatar. However, the bottleneck wasn't the GPU. Reliability : Despite using the same image, some hosts crashed every 60 seconds. We implemented a mechanism to automatically switch to a different host. Startup Speed : Reduced the time from pod startup to streaming start from 4 minutes to 95 seconds. These three aspects seem independent but are actually interconnected. Faster startup enabled practical host switching, and understanding capacity allowed us to set prices. Let's dive into each one. 1. How Many Avatars Can Run on a Single GPU? - Measured Result: 4 The first number we desperately needed was "how many avatars can run on a single GPU." Without this, we couldn't determine pricing, and without pricing, we couldn't assess the business viability. Estimates were useless, so we measured it. Here are the results: Item Measured Value GPU RTX 4000 Ada (Community type, $0.28/hour) Simultaneous Streams 4 avatars maintaining 720p30 in real-time (Recorded segment: 89 seconds / 89 seconds) GPU Usage 26% Bottlenec
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