Application packager that bundles code and dependencies into portable containers.
Image
Template for a container. Defines structure once and use multiple times easily. Stored locally or on hub.docker.com.
Container
Running instance of an image. The actual process/execution on the system. Multiple containers can run from the same image. Data is not stored (lost when container stops).
Volume
Where data persists in Docker. Stores data outside the container so it survives restarts.
# Running containersdocker ps# All containers (including stopped)docker ps -a# Custom format (more readable)docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
Start / Stop
# Stop gracefully (sends SIGTERM, waits 10s, then SIGKILL)docker stop meu-nginx# Stop immediately (SIGKILL direct — use only if necessary)docker kill meu-nginx# Start stopped containerdocker start meu-nginx# Restartdocker restart meu-nginx
Remove
# Remove stopped containerdocker rm meu-nginx# Force remove running containerdocker rm -f meu-nginx# Remove all stopped containersdocker container prune
Logs
# View all logsdocker logs meu-nginx# Follow logs in real-time (like tail -f)docker logs -f meu-nginx# View only last 50 linesdocker logs --tail 50 meu-nginx# Logs with timestampdocker logs -t meu-nginx
Enter container
# Open bash terminal in containerdocker exec -it meu-nginx bash# If image doesn't have bash, try shdocker exec -it meu-nginx sh# Execute single command without enteringdocker exec meu-nginx ls /var/www/html
Inspect
# Detailed container information (JSON)docker inspect meu-nginx# View CPU, memory and network usage in real-timedocker stats# Stats for specific containerdocker stats meu-nginx
Managed by Docker. Located in /var/lib/docker/volumes/. Best for databases.
Bind Mount
Connects specific host folder to container. Ideal for development (see changes live).
tmpfs Mount
Storage in RAM memory. Temporary, very fast. For sensitive data in memory.
Named Volumes in Practice
Create and use volumes
# Create a volume manuallydocker volume create dados-postgres# List volumesdocker volume ls# Inspect a volume (see physical location, etc)docker volume inspect dados-postgres# Use the volume in containerdocker run -d \ --name postgres \ -v dados-postgres:/var/lib/postgresql/data \ -e POSTGRES_PASSWORD=senha \ postgres:15# If you remove and recreate container, data persists!docker rm -f postgresdocker run -d \ --name postgres \ -v dados-postgres:/var/lib/postgresql/data \ -e POSTGRES_PASSWORD=senha \ postgres:15# Data is still there!
Bind mounts are essential for development. They mirror your local folder inside the container — any code changes are reflected immediately without rebuilding the image.
Development with bind mount
# Mount current folder inside containerdocker run -d \ --name app-dev \ -p 3000:3000 \ -v $(pwd):/app \ -v /app/node_modules \ node:20-alpine \ sh -c 'npm install && npm run dev'# What happened:# -v $(pwd):/app = current host folder mapped to /app in container# -v /app/node_modules = anonymous volume for node_modules (won't overwrite!)# On Windows PowerShell, use ${PWD} instead of $(pwd)docker run -v ${PWD}:/app ...
Like COPY, but supports URLs and automatically extracts tar files.
RUN comando
Executes command during image BUILD (install packages, etc).
CMD ["cmd", "arg"]
Default command when starting container. Can be overridden.
ENTRYPOINT ["cmd"]
Fixed entry point of container. CMD becomes its arguments.
ENV VAR=VALOR
Defines environment variable available at runtime.
ARG VAR=VALOR
Variable available ONLY during build time.
EXPOSE porta
Documents which port container will use (doesn’t open automatically).
VOLUME /caminho
Declares a volume mount point.
USER usuario
Defines user that runs subsequent commands (security).
Example Dockerfile
Multi-stage Node.js Dockerfile
# ─────────────────────────────────────────────────────────────# STAGE 1: Install dependencies# ─────────────────────────────────────────────────────────────FROM node:20-alpine AS dependencies# Install native dependencies if necessary# (bcrypt, sharp and others need build tools)RUN apk add --no-cache python3 make g++WORKDIR /app# Copy ONLY dependency files first# This leverages Docker cache:# If package.json didn't change, this layer is reusedCOPY package.json package-lock.json ./# Install production dependenciesRUN npm ci --only=production# ─────────────────────────────────────────────────────────────# STAGE 2: Final image (smaller and more secure)# ─────────────────────────────────────────────────────────────FROM node:20-alpine# Create non-root user to run application (security!)RUN addgroup -S appgroup && adduser -S appuser -G appgroupWORKDIR /app# Copy node_modules from previous stageCOPY --from=dependencies /app/node_modules ./node_modules# Copy application codeCOPY . .# Change file owner to created userRUN chown -R appuser:appgroup /app# Switch to non-root userUSER appuser# Document port (good practice, not mandatory)EXPOSE 3000# Environment variables with default valuesENV NODE_ENV=productionENV PORT=3000# Check if application is healthyHEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"# Start applicationCMD ["node", "src/server.js"]
Building and Publishing Images
Build image
# Build image with tag 'minha-app:1.0'docker build -t minha-app:1.0 .# The dot (.) indicates Dockerfile is in current folder# Use Dockerfile in different locationdocker build -f caminho/Dockerfile -t minha-app .# View layers and image sizedocker history minha-app:1.0
Publish to Docker Hub
# Login to Docker Hubdocker login# Tag image with your Docker Hub usernamedocker tag minha-app:1.0 seuusuario/minha-app:1.0# Push to Docker Hubdocker push seuusuario/minha-app:1.0
Tool to manage containers. Replaces docker run commands. Write everything in a YAML file and start services together.
docker-compose.yml Structure
A Compose file has four main sections: version, services, volumes, and networks.
docker-compose.yml
version: '3.8'# ─── SERVICES ─────────────────────────────────────────────────services: # Each service is a container nome-do-servico: image: imagem:tag # OR build: # Build from Dockerfile context: . # Folder with Dockerfile dockerfile: Dockerfile # File name (if not 'Dockerfile') container_name: meu-app # Fixed container name ports: - "HOST:CONTAINER" # Port mapping environment: # Environment variables - VARIAVEL=valor DATABASE_URL: postgres://user:senha@db/meudb env_file: # Or load from .env file - .env volumes: # Volumes and bind mounts - dados-nomeados:/var/dados - ./pasta-local:/app depends_on: # Startup order db: # Wait for 'db' to be 'healthy' condition: service_healthy restart: unless-stopped # Restart policy networks: # Networks to join - minha-rede healthcheck: # Health check test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s# ─── NAMED VOLUMES ─────────────────────────────────────────volumes: dados-nomeados: # Volume managed by Docker outro-volume: external: true # Externally created volume# ─── NETWORKS ────────────────────────────────────────────────networks: minha-rede: driver: bridge
Docker Compose Commands
Start services
# Start all services in backgrounddocker compose up -d# Start and rebuild images (when Dockerfile/code changed)docker compose up -d --build# Start only specific servicedocker compose up -d nome-do-servico
Stop services
# Stop containers (keeps volumes and networks)docker compose stop# Stop and REMOVE containers and networks (volumes remain)docker compose down# Remove everything including volumes (CAREFUL: deletes data!)docker compose down -v
Monitor
# List project containersdocker compose ps# View logs from all servicesdocker compose logs# Follow logs in real-timedocker compose logs -f# Logs from specific servicedocker compose logs -f app
Execute commands
# Open terminal in a servicedocker compose exec app bash# Execute one-off commanddocker compose exec db psql -U usuario -d meudb# Run one-off service (without starting others)docker compose run --rm app npm test
Other commands
# View final resolved configuration (variables substituted)docker compose config# Rebuild service without stopping othersdocker compose up -d --build app# Scale a service (create multiple instances)docker compose up -d --scale app=3
# docker-compose.override.yml# This file is automatically merged with docker-compose.yml# Use for development configsversion: '3.8'services: app: build: target: development # Use dev stage from Dockerfile volumes: - .:/app # Bind mount for hot reload - /app/node_modules # Preserve container's node_modules environment: - NODE_ENV=development command: npm run dev # Override Dockerfile CMD db: ports: - "5432:5432" # Expose port to connect externally redis: ports: - "6379:6379"