# Resource
+ How to test Dockerfiles?
https://medium.com/@michamarszaek/how-to-test-dockerfiles-9a208dded84b
+ Checking your build configuration
https://docs.docker.com/build/checks/
---
---
# Confusing Concepts for Dockerfile
## **Why Use `COPY`?**
The `COPY` command copies files/folders from **your local machine** (host) into the **image** youβre building.
### Example:
```dockerfile
COPY ./my-app /var/www/html
```
This is like packing ingredients (your source code) into the meal box (image). Without `COPY`, your container would have no access to your app files.
---
## `CMD` & `ENTRYPOINT`?
In Docker, both `CMD` and `ENTRYPOINT` define the **default behavior** of a container when it runs. However, they serve **different purposes** and are used **in different scenarios**. Understanding when to use one or both depends on the level of control and flexibility you want in your container's behavior.
### πΉ CMD β Default Arguments
* **Purpose**: Provides **default arguments** to the container's main command.
* **Overridable**: Yes β arguments passed at runtime (e.g., `docker run myimage [args]`) will **override CMD**.
* **Use case**: When you want to give users the ability to **easily override the behavior** without modifying the Dockerfile.
```Dockerfile
# Example
CMD ["nginx", "-g", "daemon off;"]
```
### πΉ ENTRYPOINT β Fixed Executable
* **Purpose**: Defines the **main command** to run inside the container.
* **Overridable**: No β runtime arguments are **passed to ENTRYPOINT** as arguments, not replacements.
* **Use case**: When you want to ensure a **specific command always runs**, and only the arguments might change.
```Dockerfile
# Example
ENTRYPOINT ["nginx"]
```
### πΈ Using Both Together
You can combine them to make a **stable command structure with flexible arguments**:
```Dockerfile
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
```
* Result: `docker run myimage` runs `nginx -g daemon off;`
* You can override the CMD part like this:
```bash
docker run myimage -g "daemon on;"
```
### β When to Use Each:
#### β Use **`CMD`** when:
* You want to provide **default arguments** for a command.
* You want users to **override the command entirely** at runtime using `docker run <image> <new_command>`.
* You are building **base images** that others will extend and customize.
π **Example use case**: A Python base image
```Dockerfile
FROM python:3.12
CMD ["python3"]
```
β Users can run: `docker run myimage script.py`
#### β Use **`ENTRYPOINT`** when:
* You want the **command to always run**, regardless of what the user provides at runtime.
* You want the container to behave like a **binary** or **command wrapper**.
* You're building a final application image where **execution behavior should not be changed**.
π **Example use case**: A container that always runs a shell script
```Dockerfile
FROM alpine
ENTRYPOINT ["/entrypoint.sh"]
```
β `docker run myimage arg1 arg2` will run `/entrypoint.sh arg1 arg2`
#### β Use **`ENTRYPOINT` + `CMD`** together when:
* You want to **enforce a specific command** (via `ENTRYPOINT`) but allow **default or overridable arguments** (via `CMD`).
* This is the **most common setup** for production containers.
π **Example use case**: A web server with configurable flagsFixed command + flexible arguments ENTRYPOINT + CMD
```Dockerfile
FROM nginx
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
```
β `docker run myimage` runs `nginx -g daemon off;`
β `docker run myimage -g 'daemon on;'` overrides the CMD part only.
#### β Avoid:
* Using both in shell form (`ENTRYPOINT nginx` and `CMD -g 'daemon off;'`) β this can lead to unpredictable behavior and broken signal handling.
---
## π§ Summary | `CMD` vs `ENTRYPOINT`
* Use **`CMD`** when you want **default, overridable parameters**.
* Use **`ENTRYPOINT`** when you want to **enforce the command being run**.
* **Use both together** when you want fixed commands with flexible default arguments.
| Situation | Use |
| ------------------------------------------------------------- | -------------------- |
| Building a base image for general use | `CMD` |
| Building a container with one fixed job | `ENTRYPOINT` |
| Fixed command + flexible arguments | `ENTRYPOINT` + `CMD` |
| You want `docker run <image>` to feel like running a CLI tool | `ENTRYPOINT` |
| Scenario | Use `CMD` | Use `ENTRYPOINT` |
| -------------------------------------------------------- | --------- | ---------------------- |
| Want to allow user to override full command easily | β | β |
| Want to always run a specific program (e.g., app binary) | β | β |
| Want to provide default Fixed command + flexible arguments ENTRYPOINT + CMD
parameters but allow overrides | β | β (combined use) |
| Writing a base image meant to be extended | β | Usually not |
| Writing a final application container | Maybe | β (for predictability) |
---
---
# TEST Dockerfile
## β STEP 1 β Build the Docker Image
Open terminal and navigate to the folder where your Dockerfile is:
```bash
cd path/to/your/nginx-folder
```
Then run:
```bash
docker build -t my_nginx_image .
```
* `-t my_nginx_image` gives your image a name.
* `.` means build from the current directory.
β **Success looks like**: β`Successfully tagged my_nginx_image:latest`β
---
## β STEP 2 β Run the Container
Because port `443` is privileged (<1024), beginners often get permission errors. So map containerβ Docker image
docker build -t my-nginx-image .s port `443` to a higher host port, like `8443`:
```bash
docker run -d --rm -p 8443:443 --name my_nginx_container my_nginx_image
```
Fixed command + flexible arguments ENTRYPOINT + CMD
* `-d` = detached (background mode)
* `--rm` = auto remove container on stop
* `-p 8443:443` = map host port 8443 β container port 443
* `--name my_nginx_container` = name your container
* `my_nginx_image` = name of the image you built
---
## β STEP 3 β Test the Container
### β Option A: Use `curl`
Run this:
```bash
curl -k https://localhost:8443
```
* `-k` = skip SSL cert validation (because it's self-signed)
If Nginx is running correctly, you should see HTML content or a response (even if empty). If not, youβll get an error.
---Fixed command + flexible arguments ENTRYPOINT + CMD
### β Option B: Use Browser
Open your browser and go to:
```
https://localhost:8443
```
Youβll probably see a **"Your connection is not private" warning** β thatβs expected due to the sel Docker image
docker build -t my-nginx-image .f-signed certificate.
Click **βProceed anywayβ** to view the site.
---
## β STEP 4 β Check Container Logs (Optional)
If you need to debug:
```bash
docker logs my_nginx_contaFixed command + flexible arguments ENTRYPOINT + CMD
iner
```
To stop the container:
```bash
docker stop my_nginx_container
```
---
## β SUMMARY
| Step | Command |
| ----------------- | ------------------------------------------------------------------------- |
| π§ Build image | `docker build -t my_nginx_image .` |
| βΆ Run container | `docker run -d --rm -p 8443:443 --name my_nginx_container my_nginx_image` |
| π Test with curl | `curl -k https://localhost:8443` |
| π§ͺ View logs | `docker logs my_nginx_container` |
| β Stop container | `docker stop my_nginx_container` |
---
# Essentia Docker image
docker build -t my-nginx-image .l Docker commands
## π§± 1. **Building Docker Images**
### π¨ Build a Docker image
```bash
docker build -t my-nginx-image ./nginx
docker build -t my-wordpress-image ./wordpress
docker build -t my-mariadb-image ./mariadb
```
* `-t` gives the image a name
* `./folder` points to where the Dockerfile is
---
## βΆοΈ 2. **Running Docker Containers**
### π Run a container from an image
```bash
docker run -d --name nginx-server -p 8080:80 my-nginx-image
docker run -d --name wordpress-app -p 9000:9000 my-wordpress-image
docker run -d --name mariadb-server -e MYSQL_ROOT_PASSWORD=rootpass -e MYSQL_DATABASE=wordpress my-mariadb-image
```
> `-e` sets environment variables like passwords and database names.
---
## ποΈ 3. **Volumes (Persistent Storage)**
### π¦ Create and use named volumes
```bash
docker volume create wordpress-data
docker volume create db-data
```
### π Attach volume to container
```bash
docker run -d \
--name wordpress-app \
-v wordpress-data:/var/www/html \
my-wordpress-image
```
```bash
docker run -d \
--name mariadb-server \
-v db-data:/var/lib/mysql \
my-mariadb-image
```
---
## π 4. **Monitoring & Debugging**
### π See all running containers
```bash
docker ps
```
### π See logs of a container
```bash
docker logs wordpress-app
```
### π§Ό Enter the shell inside a running container
```bash
docker exec -it wordpress-app bash
```
---
## β 5. **Stopping and Removing**
### π Stop a running container
```bash
docker stop wordpress-app
```
### ποΈ Remove a container
```bash
docker rm wordpress-app
```
### β Remove an image
```bash
docker rmi my-wordpress-image
```
---
## π 6. **Using Docker Compose** (recommended for multi-container setups)
### βΆοΈ Start services from `docker-compose.yml`
```bash
docker-compose up -d
```
### π Restart
```bash
docker-compose restart
```
### π Stop all services
```bash
docker-compose down
```
---
## π§ Summary Sheet
| Task | Command Example |
| ------------------------- | -------------------------------------------- |
| Build an image | `docker build -t my-image .` |
| Run a container | `docker run -d --name my-container my-image` |
| Create a volume | `docker volume create my-volume` |
| View logs | `docker logs my-container` |
| Enter shell | `docker exec -it my-container bash` |
| Stop a container | `docker stop my-container` |
| Delete a container/image | `docker rm` / `docker rmi` |
| Run multi-container stack | `docker-compose up -d` |