Add: Docker

This commit is contained in:
Óscar M. Lage 2024-11-28 22:53:45 +01:00
parent 4c8288c0d2
commit ce01bcc3d4
8 changed files with 374 additions and 25 deletions

8
.air.bot.toml Normal file
View File

@ -0,0 +1,8 @@
root = "."
tmp_dir = "tmp_bot"
[build]
cmd = "go build -o ./tmp_bot/main ./cmd/bot/main.go"
bin = "./tmp_bot/main"
delay = 1000

8
.air.web.toml Normal file
View File

@ -0,0 +1,8 @@
root = "."
tmp_dir = "tmp_web"
[build]
cmd = "go build -o ./tmp_web/main ./cmd/web/main.go"
bin = "./tmp_web/main"
delay = 1000

26
Dockerfile.bot Normal file
View File

@ -0,0 +1,26 @@
FROM golang:1.21.4
ARG DOCKER_ENV=production # Set default build-time value, not persisted in the container
ENV DOCKER_ENV=${DOCKER_ENV} # Set runtime environment variable inside the container
WORKDIR /code
RUN echo "Building with DOCKER_ENV=${DOCKER_ENV}"
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go mod tidy && \
if [ "$DOCKER_ENV" = "local" ]; then \
echo "Local environment detected, installing Air..."; \
go install github.com/cosmtrek/air@v1.49.0; \
fi
CMD if [ "$DOCKER_ENV" = "local" ]; then \
echo "Local environment detected, running Air..." && \
air -c .air.bot.toml; \
else \
echo "Production environment detected, building and running bot..."; \
go build -o bot ./cmd/bot/main.go && ./bot; \
fi

26
Dockerfile.web Normal file
View File

@ -0,0 +1,26 @@
FROM golang:1.21.4
ARG DOCKER_ENV=production # Set default build-time value, not persisted in the container
ENV DOCKER_ENV=${DOCKER_ENV} # Set runtime environment variable inside the container
WORKDIR /code
RUN echo "Building with DOCKER_ENV=${DOCKER_ENV}"
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go mod tidy && \
if [ "$DOCKER_ENV" = "local" ]; then \
echo "Local environment detected, installing Air..."; \
go install github.com/cosmtrek/air@v1.49.0; \
fi
CMD if [ "$DOCKER_ENV" = "local" ]; then \
echo "Local environment detected, running Air..." && \
air -c .air.web.toml; \
else \
echo "Production environment detected, building and running web..."; \
go build -o web ./cmd/web/main.go && ./web; \
fi

220
Makefile Normal file
View File

@ -0,0 +1,220 @@
##
# Makefile to help manage docker-compose services
#
# Include environment files
include .env
export
# Variables
THIS_FILE := $(lastword $(MAKEFILE_LIST))
DOCKER := $(shell which docker)
DOCKER_COMPOSE := $(shell which docker-compose)
IMAGE_DEFAULT := web
CONTAINER_DEFAULT := web
SHELL_CMD := /bin/bash
# Docker compose files
DOCKER_COMPOSE_FILES := -f docker-compose.yml
ifeq ($(DOCKER_ENV),local)
DOCKER_COMPOSE_FILES := -f docker-compose.yml
endif
ifeq ($(DOCKER_ENV),production)
DOCKER_COMPOSE_FILES := -f docker-compose.yml
endif
# Services
SERVICES_DEFAULT := bot web
ifeq ($(DOCKER_ENV),local)
SERVICES_DEFAULT := bot web
endif
ifeq ($(DOCKER_ENV),production)
SERVICES_DEFAULT := bot web
endif
SERVICE_DEFAULT := bot
container ?= $(CONTAINER_DEFAULT)
image ?= $(IMAGE_DEFAULT)
service ?=
services ?= $(SERVICES_DEFAULT)
.DEFAULT_GOAL := help
##
# help
#
help:
ifeq ($(CONTAINER_DEFAULT),)
$(warning WARNING: CONTAINER_DEFAULT is not set. Please edit makefile)
endif
@echo
@echo "Make targets:"
@echo
@cat $(THIS_FILE) | \
sed -n -E 's/^([^.][^: ]+)\s*:(([^=#]*##\s*(.*[^[:space:]])\s*)|[^=].*)$$/ \1 \4/p' | \
sort -u | \
expand -t15
@echo
@echo
@echo "Target arguments:"
@echo
@echo " " "service" "\t" "Target service for docker-compose actions (default=all-services)"
@echo " " " " "\t" " - make start"
@echo " " " " "\t" " - make start service=app"
@echo " " "services" "\t" "Target services for docker-compose actions (default=all-services, space separated)"
@echo " " " " "\t" " - make stop services='app db'"
@echo " " "container""\t" "Target container for docker actions (default='$(CONTAINER_DEFAULT)')"
@echo " " " " "\t" " - make bash container=$(container)"
@echo " " "image" "\t" "Target image for interactive shell (default='$(IMAGE_DEFAULT)')"
@echo " " " " "\t" " - make it image=$(image)"
##
# services
#
services: ## Lists services
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) ps --services
##
# start
#
all: dev ## See 'dev'
start: dev ## See 'dev'
dev: ## Start containers for development [service|services]
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) up -d $(services)
$(MAKE) logs
##
# stop
#
stop: ## Stop containers [service|services]
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) stop $(services)
##
# restart
#
restart: ## Restart containers [service|services]
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) restart $(services)
##
# down
#
down: ## Removes containers (preserves images and volumes)
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down
##
# build
#
build: ## Builds service images [service|services]
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) build --build-arg DOCKER_ENV=${DOCKER_ENV} $(services)
##
# rebuild
#
rebuild: ## Build containers without cache [service|services]
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) build --build-arg DOCKER_ENV=${DOCKER_ENV} --no-cache $(services)
##
# ps
#
status: ps ## See 'ps'
ps: ## Show status of containers [service|services]
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) ps $(services)
##
# interact
#
interact: it ## See `it'
it: ## Run a new container in interactive mode. Needs image name [image]
ifeq ($(image),)
$(error ERROR: 'image' is not set. Please provide 'image=' argument or edit makefile and set CONTAINER_DEFAULT)
endif
@echo
@echo "Starting interactive shell ($(SHELL_CMD)) in image container '$(image)'"
@$(DOCKER) run -it --entrypoint "$(SHELL_CMD)" $(image)
##
# bash
#
sh: bash ## See 'bash'
shell: bash ## See 'bash'
bash: ## Brings up a shell in default (or specified) container [container]
ifeq ($(container),)
$(error ERROR: 'container' is not set. Please provide 'container=' argument or edit makefile and set CONTAINER_DEFAULT)
endif
@echo
@echo "Starting shell ($(SHELL_CMD)) in container '$(container)'"
@$(DOCKER) exec -it "$(container)" "$(SHELL_CMD)"
##
# attach
#
at: attach ## See 'attach'
attach: ## Attach to a running container [container]
ifeq ($(container),)
$(error ERROR: 'container' is not set. Please provide 'container=' argument or edit makefile and set CONTAINER_DEFAULT)
endif
@echo
@echo "Attaching to '$(container)'"
@$(DOCKER) attach $(container)
##
# log
#
log: ## Shows log from a specific container (in 'follow' mode) [container]
ifeq ($(container),)
$(error ERROR: 'container' is not set. Please provide 'container=' argument or edit makefile and set CONTAINER_DEFAULT)
endif
@echo
@echo "Log in $(container)"
@$(DOCKER) logs -f $(container)
##
# logs
#
logs: ## Shows output of running containers (in 'follow' mode) [service|services]
@echo
@echo "Logs in $(services)"
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) logs -f $(services)
##
# rmimages
#
rmimages: ## Remove images
@echo
@echo "Remove local images"
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down --rmi local
##
# clean
#
clean: ## Remove containers, images and volumes
@echo
@echo "Remove containers, images and volumes"
@$(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) down --volumes --rmi all
%:
@:
.PHONY: %

View File

@ -1,6 +1,46 @@
# Proyecto HeatingEvent
# Proyecto Heating Monitor
Este proyecto gestiona eventos relacionados con el encendido y apagado de sistemas de calefacción, ofreciendo tres funcionalidades principales: una aplicación web, un bot de Telegram y un comando para importar datos desde un archivo CSV a la base de datos.
Este proyecto gestiona eventos relacionados con el encendido y apagado de sistemas de calefacción, ofreciendo tres funcionalidades principales:
- Una aplicación web
- Un bot de Telegram
- Un comando para importar datos desde un archivo CSV a la base de datos.
## Configuración
1. Crear archivo .env
Copia el archivo .env.sample a .env y configura las variables de entorno necesarias:
```sh
$ cp .env.sample .env
```
Luego edita el archivo .env con los valores correspondientes:
```ini
# Telegram Bot Configuration
TELEGRAM_TOKEN=xxx:yyy
TELEGRAM_CHATID=123123123
# Web Server Configuration
WEB_PORT=9900
```
2. Base de Datos
El proyecto utiliza una base de datos `SQLite` para almacenar los eventos de calefacción. La configuración de la base de datos se gestiona automáticamente a través del código en el archivo `internal/config/db.go`. Asegúrate de que el archivo de la base de datos se encuentra en la ubicación correcta para que la conexión funcione correctamente.
## Docker
Este proyecto puede ejecutarse fácilmente con Docker. Se han configurado dos entornos: `local` y `production`. En el entorno `local`, se utiliza `Air` para recargar automáticamente el código durante el desarrollo, mientras que en `production` se compila el binario y se ejecuta directamente. Asegúrate de tener Docker y Docker compose instalados en tu sistema.
El `Makefile` ha sido configurado para facilitar la construcción y ejecución de Docker con el argumento `--build-arg`, que pasará la variable de entorno `DOCKER_ENV` para que determine el mismo. Dicha variable se lee del archivo `.env`:
`--build-arg DOCKER_ENV=${DOCKER_ENV}`: Utiliza esta variable para determinar el entorno de ejecución (`local` o `production`), lo que afecta tanto la construcción de los binarios como el comportamiento del contenedor.
```sh
$ make build
$ make rebuild
$ make start
```
## Comandos disponibles
@ -9,6 +49,7 @@ Este proyecto gestiona eventos relacionados con el encendido y apagado de sistem
Este comando inicia un servidor web que permite visualizar los eventos de calefacción a través de una interfaz web.
#### Uso:
```bash
$ go run cmd/web/main.go
```
@ -18,9 +59,11 @@ $ go run cmd/web/main.go
- WEB_PORT: Puerto en el que se ejecuta el servidor web. Puedes configurarlo en el archivo `.env`.
### 2. Comando Bot
Este comando inicia un bot de Telegram que permite interactuar con el sistema de calefacción a través de mensajes.
#### Uso:
```sh
$ go run cmd/bot/main.go
```
@ -35,6 +78,7 @@ $ go run cmd/bot/main.go
Este comando importa los datos de un archivo CSV (con formato específico) a la base de datos SQLite, creando eventos de encendido y apagado en función de la información proporcionada en el archivo.
#### Uso:
```
$ go run cmd/import/main.go -f /ruta/al/archivo.csv
-f, --file: Especifica la ruta del archivo CSV a importar.
@ -42,26 +86,7 @@ $ go run cmd/import/main.go -f /ruta/al/archivo.csv
(útil para verificar la información antes de insertarla).
```
#### Configuración
1. Crear archivo .env
Copia el archivo .env.sample a .env y configura las variables de entorno necesarias:
```sh
$ cp .env.sample .env
```
Luego edita el archivo .env con los valores correspondientes:
```ini
# Telegram Bot Configuration
TELEGRAM_TOKEN=xxx:yyy
TELEGRAM_CHATID=123123123
# Web Server Configuration
WEB_PORT=9900
```
2. Base de Datos
El proyecto utiliza una base de datos SQLite para almacenar los eventos de calefacción. La configuración de la base de datos se gestiona automáticamente a través del código en el archivo `internal/config/db.go`. Asegúrate de que el archivo de la base de datos se encuentra en la ubicación correcta para que la conexión funcione correctamente.
### Dependencias
## Dependencias
Este proyecto utiliza varias dependencias de Go. Asegúrate de tenerlas instaladas y configuradas correctamente:
@ -69,7 +94,7 @@ Este proyecto utiliza varias dependencias de Go. Asegúrate de tenerlas instalad
$ go mod tidy
```
### Estructura del Proyecto
## Estructura del Proyecto
```sh
.
@ -84,7 +109,7 @@ $ go mod tidy
└── README.md # Este archivo
```
### Contribución
## Contribución
Si deseas contribuir a este proyecto, por favor sigue estos pasos:

33
docker-compose.yml Normal file
View File

@ -0,0 +1,33 @@
name: "heating-monitor"
version: "3.8"
services:
bot:
container_name: bot
hostname: bot
env_file:
- ./.env
build:
context: .
dockerfile: Dockerfile.bot
volumes:
- ./:/code/
stdin_open: true
tty: true
restart: always
web:
container_name: web
hostname: web
env_file:
- ./.env
build:
context: .
dockerfile: Dockerfile.web
volumes:
- ./:/code/
stdin_open: true
tty: true
ports:
- ${WEB_PORT}:${WEB_PORT}
restart: always

View File

@ -1,10 +1,13 @@
# Docker
DOCKER_ENV=local
PROJECT_NAME=heating-monitor
# Telegram
TELEGRAM_TOKEN=aaaa:bbbb
TELEGRAM_CHATID=123123
# Web
WEB_PORT=9900
PROGRAM_AUTHOR="oscarmlage"
PROGRAM_LINK="https://oscarmlage.com"
PROGRAM_AVATAR="https://mastodon.bofhers.es/system/accounts/avatars/108/369/580/175/949/602/original/01f8e5e7fcc34119.jpg"