cmc/cleberg.net
My personal web garden & blog.
clone: git clone https://gitbay.org/cmc/cleberg.net.git
main: content/blog/2024-04-08-docker-local-web-server.org · raw
1#+date: [2024-04-08 Mon 00:00:00]
2#+title: Local Web Dev Server with Docker and Nginx
3#+description: Setting up a local web server for development with Docker and Nginx.
4#+slug: docker-local-web-server
5#+filetags: :self-hosting:web:
6
7When developing websites locally, I often use a simple Python web server to
8observe the changes.
9
10#+begin_src sh
11python3 -m http.server
12#+end_src
13
14However, this approach has its limitations. For example, this approach does not
15enable logging or access controls. You also need to customize =SimpleHTTPServer=
16if you have advanced needs from your web server.
17
18So, I went to find an alternative that is almost as easy and far more extensible
19and found Docker Desktop to be a suitable replacement.
20
21* Docker Desktop
22
23** Installation
24
25[[https://www.docker.com/products/docker-desktop/][Docker Desktop]] is a desktop GUI for the phenomenal Docker container software.
26This allows you to manage containers, images, volumes, environments, and
27extensions via an easy-to-use GUI.
28
29To install, open the link above and click the =Download= button for your
30platform. I'm going through this process on an M2 Macbook, so I downloaded the
31Mac - Apple Chip version.
32
33Open the installer and follow the installation process until the application
34finishes the installation process.
35
36#+caption: Docker Desktop on macOS
37#+attr_html: :alt The Containers home page of the Docker Desktop app on macOS.
38[[https://img.cleberg.net/blog/20240408-docker-local-web-server/docker-desktop.webp]]
39
40** Creating an Nginx Container
41
42I prefer to use the command line to create containers, so the following commands
43will be input via the terminal.
44
45The following command will create a container, using the =nginx= image:
46
471. =-d=: Run this container as a daemon (detach)
482. =-p=: Allocate a port in the format =<external>:<internal>=
493. =-i=: Keep STDIN open even if not attached
504. =-t=: Allocate a pseudo-TTY
515. =-p=: Allocate a port in the format =<external>:<internal>=
526. =--rm=: Remove the container once it's done running
53
54#+begin_src sh
55docker run -it --rm -d -p 8000:80 --name web nginx
56#+end_src
57
58You can navigate to [[http://localhost:8000]] to see the resulting page.
59
60#+caption: Default Nginx Container
61#+attr_html: :alt The generic "Welcome to nginx!" page viewable at localhost:8000.
62[[https://img.cleberg.net/blog/20240408-docker-local-web-server/default-container.webp]]
63
64** Customizing the Nginx Container
65
66Now that I have a container running the Nginx web server, I need to link some
67volumes so that I can modify the site configuration and provide the web files to
68serve.
69
70Let's start with the new command, which adds two volumes:
71
721. =<your_content>:/usr/share/nginx/html=: This is the directory where you will
73 provide the web pages for the server to serve.
742. =<your_config>:/etc/nginx/conf.d/default.conf=: This is the Nginx
75 configuration file for your site.
76
77To see the updates, you can delete the previous container in the GUI or run
78=docker stop web= to stop the container. Once stopped, you can run the new
79=docker run= command below.
80
81#+begin_src sh
82docker 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
83#+end_src
84
85Here's an example of my development configuration file.
86
87#+begin_src conf
88# nginx-config.conf
89server {
90 server_name cleberg.net www.cleberg.net;
91
92 root /usr/share/nginx/html;
93 index index.html;
94 autoindex on;
95
96 access_log /var/log/nginx/cleberg.net.access.log;
97 error_log /var/log/nginx/cleberg.net.error.log;
98
99 location / {
100 try_files $uri $uri/ =404;
101 }
102
103 listen [::]:80;
104 listen 80;
105}
106#+end_src
107
108#+caption: Deploying My Website via Docker
109#+attr_html: :alt A view of cleberg.net on the localhost, as the docker container is pointing to the cleberg.net repository directory.
110[[https://img.cleberg.net/blog/20240408-docker-local-web-server/custom-container.webp]]
111
112* Customizing Deployment Actions
113
114I am currently blogging with [[https://emacs.love/weblorg/][weblorg]], which uses a custom =publish.el= file to
115build the static site. Within this file, I have configured my deployment process
116to check for the =ENV= variable in the shell and if it's set to =prod=, the script
117will set the base URLs to =https://cleberg.net=. If not, it sets the base URLs
118to =localhost:8000= (which matches the port used in the container above).
119
120Therefore, I have modified my =build.sh= script to build with =localhost= URLs
121if =ENV= is not set to =prod=. It also prevents the build process from sending
122the built files to the production web server.
123
124#+begin_src sh
125#!/bin/bash
126
127if [ "$ENV" == "prod" ]; then
128 echo "Environment = Production" && \
129 rm -rf .build/* && \
130 emacs --script publish.el && \
131 scp -r .build/* ubuntu:/var/www/cleberg.net/
132else
133 echo "Environment = Development" && \
134 rm -rf .build/* && \
135 emacs --script publish.el
136fi
137#+end_src
138
139You can modify the container in numerous ways and this approach allows you to
140create complex scenarios for your web development purposes. I highly recommend
141switching over to a container-based approach for simple, local web development.