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.