1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
+++
date = 2024-04-08
title = "Using Docker Desktop to Create a Development Web Server"
description = ""
draft = false
+++
When developing websites locally, I often use a simple Python web server to
observe the changes.
```sh
python3 -m http.server
```
However, this approach has its limitations. For example, this approach does not
enable logging or access controls. You also need to customize `SimpleHTTPServer`
if you have advanced needs from your web server.
So, I went to find an alternative that is almost as easy and far more extensible
and found Docker Desktop to be a suitable replacement.
# Docker Desktop
## Installation
[Docker Desktop](https://www.docker.com/products/docker-desktop/) is a desktop
GUI for the phenomenal Docker container software. This allows you to manage
containers, images, volumes, environments, and extensions via an easy-to-use
GUI.
To install, open the link above and click the `Download` button for your
platform. I'm going through this process on an M2 Macbook, so I downloaded the
Mac - Apple Chip version.
Open the installer and follow the installation process until the application
finishes the installation process.

## Creating an Nginx Container
I prefer to use the command line to create containers, so the following commands
will be input via the terminal.
The following command will create a container, using the `nginx` image:
1. `-d`: Run this container as a daemon (detach)
2. `-p`: Allocate a port in the format `<external>:<internal>`
3. `-i`: Keep STDIN open even if not attached
4. `-t`: Allocate a pseudo-TTY
5. `-p`: Allocate a port in the format `<external>:<internal>`
6. `--rm`: Remove the container once it's done running
```sh
docker run -it --rm -d -p 8000:80 --name web nginx
```
You can navigate to <http://localhost:8000> to see the resulting page.

## Customizing the Nginx Container
Now that I have a container running the Nginx web server, I need to link some
volumes so that I can modify the site configuration and provide the web files to
serve.
Let's start with the new command, which adds two volumes:
1. `<your_content>:/usr/share/nginx/html`: This is the directory where you will
provide the web pages for the server to serve.
2. `<your_config>:/etc/nginx/conf.d/default.conf`: This is the Nginx
configuration file for your site.
To see the updates, you can delete the previous container in the GUI or run
`docker stop web` to stop the container. Once stopped, you can run the new
`docker run` command below.
```sh
docker run -it -d -p 8000:80 --name web -v ~/Source/cleberg.net/.build:/usr/share/nginx/html -v ~/Source/cleberg.net/nginx-config.conf:/etc/nginx/conf.d/default.conf nginx
```
Here's an example of my development configuration file.
``` conf
# nginx-config.conf
server {
server_name cleberg.net www.cleberg.net;
root /usr/share/nginx/html;
index index.html;
autoindex on;
access_log /var/log/nginx/cleberg.net.access.log;
error_log /var/log/nginx/cleberg.net.error.log;
location / {
try_files $uri $uri/ =404;
}
listen [::]:80;
listen 80;
}
```

# Customizing Deployment Actions
I am currently blogging with [weblorg](https://emacs.love/weblorg/), which uses
a custom `publish.el` file to build the static site. Within this file, I have
configured my deployment process to check for the `ENV` variable in thesh and if
it's set to `prod`, the script will set the base URLs to `https://cleberg.net`.
If not, it sets the base URLs to `localhost:8000` (which matches the port used
in the container above).
Therefore, I have modified my `build.sh` script to build with `localhost` URLs
if `ENV` is not set to `prod`. It also prevents the build process from sending
the built files to the production web server.
```sh
#!/bin/bash
if [ "$ENV" == "prod" ]; then
echo "Environment = Production" && \
rm -rf .build/* && \
emacs --script publish.el && \
scp -r .build/* ubuntu:/var/www/cleberg.net/
else
echo "Environment = Development" && \
rm -rf .build/* && \
emacs --script publish.el
fi
```
You can modify the container in numerous ways and this approach allows you to
create complex scenarios for your web development purposes. I highly recommend
switching over to a container-based approach for simple, local web development.
|