Skip to content
/ snipbox Public

Repo for snippetbox project as part of Let's Go! book by Alex Edwards.

License

Notifications You must be signed in to change notification settings

nmdra/snipbox

Repository files navigation

Snipbox

Go 1.23

Repo for snippetbox project as part of Let's Go! book by Alex Edwards (found here)

✨ My Changes

This section highlights the modifications made to the original project as described in the Let's Go book:

  • Creating a Docker-driven Go development workflow
  • Add live realod using air-verse/air
  • Add Docker image (production)

Setup Mysql docker container

Docker Compose File

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: snipbox-dev
    ports:
      - "4000:4000" # default app port
      - "4001:4001" # air proxy port (Optional)
    environment:
      - PORT=4000 # default app port 
    volumes:
      - ./:/app
    networks:
      - snipbox-net
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:lts 
    container_name: snipbox-db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: snippetbox
      MYSQL_USER: web
      MYSQL_PASSWORD: pass
    ports:
      - "3306:3306" # Optinal
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - snipbox-net
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 5s
      retries: 2
  
volumes:
  mysql-data:
    external: true # Use external vluume for data persistence

networks:
  snipbox-net:
    driver: bridge

Setup User

Important

We use % instead of localhost because:

  • 'localhost' restricts the user to connect only from the same machine where the MySQL server is running.
  • In this workflow, MySQL runs in a separate container, so localhost doesn't work for external connections.
  • Using % allows the user to connect from any host, enabling communication between containers.
  1. Create User
CREATE USER 'web'@'%';
  1. Grant access
GRANT SELECT, INSERT, UPDATE, DELETE ON snippetbox.* TO 'web'@'%';
-- Important: Make sure to swap 'pass' with a password of your own choosing.
ALTER USER 'web'@'%' IDENTIFIED BY 'pass';
  1. Check users
SELECT user, host FROM mysql.user;
  1. Connection String
dsn := flag.String("dsn", "web:pass@tcp(mysql:3306)/snippetbox?parseTime=true", "MySQL data source name")

Docker Compose Production

Tip

Create self signed tls certificate & create .env before run docker compose the generate_cert.go file should be located under /usr/local/go/src/crypto/tls or /usr/lib/go/src/crypto/tls (Manjaro/Arch)

Generate Certificate

mkdir -p tls
cd tls
go run /usr/local/go/src/crypto/tls/generate_cert.go --rsa-bits=2048 --host=localhost
services:
  web:
    image: ghcr.io/nmdra/snipbox:latest
    container_name: snipbox-prod
    ports:
      - "4000:4000" # default app port
    env_file:
      - .env
    volumes:
      - ./tls/:/tls/ # TLS cert directory
    networks:
      - snipbox-net
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:lts 
    # container_name: snipbox-db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: snippetbox
      MYSQL_USER: web
      MYSQL_PASSWORD: pass
    ports:
      - "3306:3306" # Expose MySQL port (Optional)
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - snipbox-net
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 5s
      retries: 2
  
volumes:
  mysql-data:
    external: true

networks:
  snipbox-net:
    driver: bridge