Back to Engineering Notes
DockerEngineering Note

8. Docker EXEC Operations

Use docker exec to enter a running Docker container, install Apache2, change its default HTTP port from 80 to 8087, and verify that the web server is running correctly.

🎯 Objective

Use docker exec to enter a running Docker container, install Apache2, change its default HTTP port from 80 to 8087, and verify that the web server is running correctly.

The main Docker command is:

bash
docker exec -it <container_name> bash

🧠 Concept

docker exec allows us to execute commands inside an already running container.

The basic syntax is:

bash
docker exec [OPTIONS] <container> <command>

For an interactive Bash shell:

bash
docker exec -it <container_name> bash

The flow is:

plain text
Docker Host
    │
    │ docker exec -it
    ▼
Running Container
    │
    ├── Install Apache
    ├── Configure Port 8087
    ├── Start Apache
    └── Test Web Server

Unlike docker run, docker exec does not create a new container. It executes a command inside an existing running container.


🔍 Step 1: Check Running Containers

List currently running containers:

bash
docker ps

Example:

plain text
CONTAINER ID   IMAGE    COMMAND   STATUS       NAMES
abc123def456   ubuntu   "bash"    Up 5 mins    kkloud

Identify the container name you want to access.


🚀 Step 2: Enter the Container

Open an interactive Bash shell:

bash
docker exec -it <container_name> bash

Example:

bash
docker exec -it kkloud bash

Command Breakdown

plain text
docker exec

Execute a command inside a running container.

plain text
-i

Keeps standard input open for interactive use.

plain text
-t

Allocates a pseudo-terminal.

Together:

plain text
-it → Interactive terminal

Finally:

plain text
bash

starts a Bash shell inside the container.


📦 Step 3: Update Package Repository

Inside the container, update the APT package index:

bash
apt update

This downloads the latest package information from the configured Ubuntu/Debian repositories.


🌐 Step 4: Install Apache2

Install Apache:

bash
apt install -y apache2

The -y option automatically confirms the installation.

Verify the installation:

bash
apache2 -v

You should see Apache version information similar to:

plain text
Server version: Apache/2.4.x
Server built: ...

⚙️ Step 5: Change Apache Port

Apache listens on port 80 by default.

The requirement is:

plain text
Default Port
80
 ↓
Change
 ↓
8087

Apache's listening port is configured in:

plain text
/etc/apache2/ports.conf

Replace:

plain text
Listen 80

with:

plain text
Listen 8087

using:

bash
sed -i 's/Listen 80/Listen 8087/' /etc/apache2/ports.conf

What sed -i Does

plain text
sed
 ↓
Search and replace text

-i
 ↓
Modify the file directly

So:

bash
sed -i 's/Listen 80/Listen 8087/' /etc/apache2/ports.conf

means:

plain text
Find:     Listen 80
Replace:  Listen 8087

🌍 Step 6: Update the Virtual Host Port

Apache's default site also expects port 80.

The configuration is located at:

plain text
/etc/apache2/sites-available/000-default.conf

Change:

plain text
<VirtualHost *:80>

to:

plain text
<VirtualHost *:8087>

using:

bash
sed -i 's/<VirtualHost \*:80>/<VirtualHost \*:8087>/' /etc/apache2/sites-available/000-default.conf

Now both configurations use:

plain text
8087

The relationship becomes:

plain text
/etc/apache2/ports.conf
        │
        └── Listen 8087

/etc/apache2/sites-available/000-default.conf
        │
        └── <VirtualHost *:8087>

🧠 Listen vs VirtualHost

These two settings have different purposes.

Listen

plain text
Listen 8087

tells Apache:

> Accept incoming connections on TCP port 8087.

VirtualHost

plain text
<VirtualHost *:8087>

tells Apache:

> Use this virtual-host configuration for requests arriving on port 8087.

For this setup, both should reference the new port.


🧪 Step 7: Validate Apache Configuration

Before starting Apache, check the configuration:

bash
apache2ctl configtest

Expected output:

plain text
Syntax OK

This is important because it catches configuration errors before the service is started.

The flow is:

plain text
Modify Configuration
        ↓
apache2ctl configtest
        ↓
    Syntax OK
        ↓
Start Apache

▶️ Step 8: Start Apache

Start the Apache service:

bash
service apache2 start

Inside many containers, service is more appropriate than:

bash
systemctl start apache2

because containers often do not run systemd as PID 1.


🔍 Step 9: Check Apache Status

Check whether Apache is running:

bash
service apache2 status

You should see output indicating that Apache is running.


🌐 Step 10: Test Apache

Test the web server from inside the container:

bash
curl http://localhost:8087

If everything is configured correctly, Apache should return the default HTML page.

The request flow is:

plain text
curl
 │
 │ http://localhost:8087
 ▼
Port 8087
 │
 ▼
Apache
 │
 ▼
Default Website
 │
 ▼
HTML Response

🔍 Optional: Verify Listening Port

You can also verify that Apache is listening on 8087.

If ss is available:

bash
ss -lntp

Or specifically:

bash
ss -lntp | grep 8087

You should see Apache listening on something equivalent to:

plain text
0.0.0.0:8087

or:

plain text
*:8087

This is important if Apache must accept connections through localhost, the container IP, and other available interfaces rather than being bound to one specific IP address.


🚪 Step 11: Exit the Container

Once verification is complete:

bash
exit

This exits the interactive shell.

It does not stop the container.

plain text
exit
 ↓
Leave container shell
 ↓
Container remains running

⚠️ Important: Container Port vs Published Port

Configuring Apache to listen on:

plain text
8087

means Apache is listening on port 8087 inside the container.

That does not automatically make port 8087 accessible from the Docker host or external network.

For example, a container created with:

bash
docker run -p 8087:8087 ...

maps:

plain text
Host :8087
    │
    │ Docker port mapping
    ▼
Container :8087
    │
    ▼
Apache

If the task only requires testing from inside the container:

bash
curl http://localhost:8087

then publishing the port may not be necessary.


🐳 docker exec vs docker run

docker run

Creates and starts a new container:

plain text
Image
  │
  │ docker run
  ▼
New Container

docker exec

Runs a command inside an existing running container:

plain text
Existing Running Container
        │
        │ docker exec
        ▼
Execute Command

Example:

bash
docker exec -it kkloud bash

does not create another container.


⚙️ Complete Workflow

Check the running container:

bash
docker ps

Enter it:

bash
docker exec -it <container_name> bash

Update packages:

bash
apt update

Install Apache:

bash
apt install -y apache2

Verify installation:

bash
apache2 -v

Change Apache's listening port:

bash
sed -i 's/Listen 80/Listen 8087/' /etc/apache2/ports.conf

Update the default virtual host:

bash
sed -i 's/<VirtualHost \*:80>/<VirtualHost \*:8087>/' /etc/apache2/sites-available/000-default.conf

Validate:

bash
apache2ctl configtest

Start Apache:

bash
service apache2 start

Check status:

bash
service apache2 status

Test:

bash
curl http://localhost:8087

🧪 Validation Checklist

[ ] Container is running
[ ] Entered container using docker exec -it
[ ] Package repository updated
[ ] Apache2 installed
[ ] Apache version verified
[ ] Listen changed from 80 to 8087
[ ] VirtualHost changed from :80 to :8087
[ ] Apache configuration returns Syntax OK
[ ] Apache service started
[ ] Apache service is running
[ ] Apache listens on port 8087
[ ] curl http://localhost:8087 returns the website
[ ] Container remains running

📌 Summary

The key Docker command is:

bash
docker exec -it <container_name> bash

Once inside the container:

bash
apt update
apt install -y apache2

apache2 -v

sed -i 's/Listen 80/Listen 8087/' /etc/apache2/ports.conf
sed -i 's/<VirtualHost \*:80>/<VirtualHost \*:8087>/' /etc/apache2/sites-available/000-default.conf

apache2ctl configtest

service apache2 start
service apache2 status

curl http://localhost:8087

The complete flow is:

plain text
Docker Host
    │
    │ docker exec -it
    ▼
Running Container
    │
    ├── apt install apache2
    │
    ├── Listen 80 → 8087
    │
    ├── VirtualHost 80 → 8087
    │
    ├── configtest
    │
    └── Start Apache
    │
    ▼
Apache :8087
    │
    │ curl localhost:8087
    ▼
Website Response ✅

The key takeaway is:

> docker exec lets us execute commands inside an existing running container. In this task, we use it to install and configure Apache to listen on port 8087 without creating a new container.