fullstack-app/
├── docker-compose.yml
├── Dockerfile
├── server.js
├── package.json
└── init.sqlCREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);
INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'), ('Bob', 'bob@example.com');const express = require('express');
const { Pool } = require('pg');
const app = express();
const pool = new Pool({
host: process.env.DB_HOST || 'db',
user: 'postgres', password: process.env.DB_PASSWORD,
database: 'fullstack',
});
app.get('/', async (req, res) => {
const { rows } = await pool.query('SELECT * FROM users');
res.json({ message: 'Hello from Docker!', users: rows });
});
app.listen(3000, () => console.log('Running on 3000 🐳'));{ "name": "fullstack-app", "scripts": { "start": "node server.js" },
"dependencies": { "express": "^4.21.0", "pg": "^8.13.0" } }FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]services:
app:
build: .
ports: ["3000:3000"]
environment: { DB_HOST: db, DB_PASSWORD: secret123 }
depends_on: [db]
db:
image: postgres:16-alpine
volumes:
- pg-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
environment: { POSTGRES_PASSWORD: secret123, POSTGRES_DB: fullstack }
volumes: { pg-data: }docker compose up -d
curl http://localhost:3000
# {"message":"Hello from Docker!","users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}
docker exec -it app sh # Vào container
docker logs -f app # Logs realtime
docker system prune -a # Dọn sạch
docker compose down # Dừng toàn bộdocker compose up -dcurl http://localhost:3000docker exec -it app sh — vào containerdocker compose down — dừng toàn bộ1. depends_on trong docker-compose.yml có tác dụng gì?
2. docker exec -it app sh dùng để làm gì?