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
|
#+date: <2024-04-08>
#+title: Using Docker Desktop to Create a Development Web Server
#+description:
#+slug: docker-local-web-server
When developing websites locally, I often use a simple Python web server to
observe the changes.
#+begin_src sh
python3 -m http.server
#+end_src
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
[[https://www.docker.com/products/docker-desktop/][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.
#+caption: Docker Desktop on macOS
[[https://media.githubusercontent.com/media/ccleberg/img/main/blog/20240408-docker-local-web-server/docker-desktop.png]]
** 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
#+begin_src sh
docker run -it --rm -d -p 8000:80 --name web nginx
#+end_src
You can navigate to [[http://localhost:8000]] to see the resulting page.
#+caption: Default Nginx Container
[[https://media.githubusercontent.com/media/ccleberg/img/main/blog/20240408-docker-local-web-server/default-container.png]]
** 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.
#+begin_src 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
#+end_src
Here's an example of my development configuration file.
#+begin_src 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;
}
#+end_src
[[https://media.githubusercontent.com/media/ccleberg/img/main/blog/20240408-docker-local-web-server/custom-container.png]]
* Customizing Deployment Actions
I am currently blogging with [[https://emacs.love/weblorg/][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.
#+begin_src 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
#+end_src
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.
|