aboutsummaryrefslogtreecommitdiff
path: root/content/blog/2024-04-08-docker-local-web-server.org
blob: 70790925bf043494277c6a21e88ce058ff8b38c5 (plain) (blame)
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
#+date: <2024-04-08>
#+title: Using Docker Desktop to Create a Development Web Server
#+description: 


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://img.cleberg.net/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://img.cleberg.net/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://img.cleberg.net/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.