Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions exercises/docker/docker-debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Docker Scenario-Based Exercises

This file contains scenario-based Docker questions to help DevOps engineers practice real-world troubleshooting and configuration tasks. Each question simulates a practical scenario with a step-by-step answer.

## Question 1: Debugging a Docker Container Failure

### Question
You’re a DevOps engineer deploying a Node.js application using Docker. You run `docker run -d -p 3000:3000 my-node-app`, but the container exits immediately. Using `docker ps -a`, you see the container status as `Exited`. How would you troubleshoot and resolve this issue?

### Answer
To troubleshoot a container exiting immediately:
1. **Check Logs**: Run `docker logs my-node-app` to view error messages. Common issues include missing dependencies (e.g., `npm install` failed) or an incorrect command.
2. **Inspect the Container**: Use `docker inspect my-node-app` to check `Config.Cmd` or `Config.Entrypoint`. Ensure the command (e.g., `node app.js`) is valid.
3. **Verify the Dockerfile**: Check if `CMD` or `ENTRYPOINT` is correct, e.g., `CMD ["node", "app.js"]`. Update and rebuild if needed: `docker build -t my-node-app .`.
4. **Test Interactively**: Run `docker run -it my-node-app sh` to debug manually (e.g., `node app.js`).
5. **Check Resources**: Ensure the host has enough memory/CPU using `docker stats`.

**Example Fix**: If logs show `node: command not found`, update the Dockerfile to use `FROM node:18`, rebuild, and rerun.

### Additional Notes
- Always start with `docker logs` for error clues.
- Use `docker ps -a` to check container status and ID.
- Common issues include missing dependencies or crashing apps.


---


## Question 2: Configuring a Multi-Container Application

### Question
As a DevOps engineer, you need to deploy a web application with a Node.js backend and a MySQL database using Docker. The Node.js app connects to MySQL on `localhost:3306`, but running `docker run` for each container separately fails because they can’t communicate. How would you set up these containers to work together?

### Answer
To make the Node.js and MySQL containers communicate:
1. **Use Docker Compose**: Create a `docker-compose.yml` file to define and link both services:
```yaml
version: '3.8'
services:
node-app:
image: my-node-app
build: .
ports:
- "3000:3000"
depends_on:
- mysql-db
environment:
- DB_HOST=mysql-db
- DB_PORT=3306
mysql-db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=secret
ports:
- "3306:3306"
```
2. **Run the Application**: Execute `docker-compose up -d` to start both containers. The `node-app` service connects to `mysql-db` using the service name (`mysql-db`) as the hostname, not `localhost`.
3. **Verify Connectivity**: Check logs with `docker-compose logs node-app` to ensure the Node.js app connects to MySQL. If it fails, verify the environment variables and MySQL’s readiness.
4. **Alternative Without Compose**: Use a custom network:
- Create a network: `docker network create my-app-network`
- Run MySQL: `docker run -d --name mysql-db --network my-app-network -e MYSQL_ROOT_PASSWORD=secret mysql:8.0`
- Run Node.js: `docker run -d --name node-app --network my-app-network -p 3000:3000 -e DB_HOST=mysql-db my-node-app`

### Additional Notes
- Docker Compose simplifies multi-container setups by managing networks and dependencies.
- Always set environment variables for database credentials to avoid hardcoding.


---


## Question 3: Optimizing a Dockerfile for CI/CD

### Question
You’re a DevOps engineer integrating a Dockerized Python application into a Jenkins CI/CD pipeline. The Dockerfile builds slowly, causing pipeline delays. How would you optimize the Dockerfile to speed up builds while maintaining functionality?

### Answer
To optimize a Dockerfile for faster CI/CD builds:
1. **Use a Smaller Base Image**: Replace heavy images like `python:3.9` with `python:3.9-slim` to reduce size and download time.
```dockerfile
FROM python:3.9-slim
```
2. **Leverage Layer Caching**: Order instructions from least to most likely to change. Copy `requirements.txt` and install dependencies before copying the app code:
```dockerfile
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
```
3. **Minimize Layers**: Combine related commands with `&&` to reduce layers:
```dockerfile
RUN pip install -r requirements.txt && rm -rf /root/.cache/pip
```
4. **Use Multi-Stage Builds**: If the app needs build tools, use a multi-stage build to keep the final image small:
```dockerfile
FROM python:3.9 AS builder
COPY requirements.txt .
RUN pip install -r requirements.txt
FROM python:3.9-slim
COPY --from=builder /usr/local/lib/python3.9 /usr/local/lib/python3.9
COPY . .
CMD ["python", "app.py"]
```
5. **Test in Jenkins**: Update the Jenkins pipeline to rebuild the image only when `Dockerfile` or code changes, using a cached image otherwise:
```groovy
pipeline {
agent any
stages {
stage('Build Docker Image') {
when { changeset "Dockerfile,**.py" }
steps { sh 'docker build -t my-python-app .' }
}
}
}
```

### Additional Notes
- Use `.dockerignore` to exclude unnecessary files (e.g., `.git`, `tests/`) from the build context.
- Monitor build times in Jenkins to confirm improvements.


*Contributed by Lahiru Galhena*