Implementando un sitio web Go en Apache
Para implementar un sitio web Go en Apache tenemos que entender como el lenguaje GO corre una app web, Go utiliza el paquete net/http(standard library) para esto, el cual provee implementación tanto para cliente HTTP como servidor http.
Posees un buen ejemplo de su uso en la documentación de este paquete(standard library):
running a websitepackage main import ( "io" "log" "net/http" ) func main() { // Hello world, the web server helloHandler := func(w http.ResponseWriter, req *http.Request) { io.WriteString(w, "Hello, world!\n") } http.HandleFunc("/hello", helloHandler) log.Fatal(http.ListenAndServe(":8080", nil)) }
Este es el ejemplo del método ListenAndServer
luego cuando corremos nuestra web con go run main.go
y vamos a nuestro navegador deberíamos ver «Hello, word» en pantalla
Excelente podemos decir que esta es nuestra primera página web en nuestro server local y cuando corremos el comando go run main.go
obtenemos «Hello, word»
Aquí podemos ver que el server está en el puerto 8080, ¿cómo podríamos hacer que apache implemente esto?
Configuración en Apache
Supongamos que ya tenemos instalado apache en la configuración para mi página web
¿Qué debería hacer para mostrar lo de mi Cliente Servider HTTP de Go?
Para ello tenemos alguna que otra manera, pero la que más nos convendrá al usar Go es hacer un reverse proxy en Apache.
gowebsite.conf<VirtualHost *:80> ServerName tu-dominio.com ProxyPreserveHost On ProxyPass / http://localhost:8888/ ProxyPassReverse / http://localhost:8888/ ErrorLog ${APACHE_LOG_DIR}/mi-app-error.log #caso que queramos un log aparte CustomLog ${APACHE_LOG_DIR}/mi-app-access.log combined </VirtualHost>
Recordemos que el archivo de configuración por lo general deberá estar en /etc/apache2/sites-available/
Hasta aquí todo bien para mi aplicación verdad ¿tengo mi server Apache y para correr el server de go corro mi go run main.go?
La respuesta a esta pregunta es no, no podemos tener nuestra consola inutilizable mientras corre el Server.
Crear un Daemon con systemd para mi Aplicación
Para poder hacer que nuestro server corra por detrás necesitaremos de un Daemon o demonio como le quiera decir, este lo que tendrá que hacer es que corra el server hasta que le digamos que lo deje de correr, concepto simple, pero aún hay que configurarlo.
Deberás crear un archivo de servicios, por lo tanto, tendrás que hacerlo en /etc/systemd/system/ si estás usando Linux Ubuntu
vim /etc/systemd/system/mygoapp.service/etc/systemd/system/mygoapp.service
[Unit] Description=Mi Aplicación Go After=network.target [Service] ExecStart=/home/tu-usuario/mi-app/mi-app-ejecutable WorkingDirectory=/home/tu-usuario/mi-app Restart=always User=tu-usuario Group=tu-grupo Environment=GIN_MODE=release [Install] WantedBy=multi-user.target
Explicación del servicio
[Unit] -contiene metadatos y dependencias sobre el servicio que se está configurando
Description – es la descripción de lo que hace nuestro servicio
After – indica que nuestro servicio será inicializado luego de estos servicios, en nuestro caso luego del servicio de red
[Service]
ExecStart – el ejecutable de la aplicación
WorkingDirectory – el directorio de la aplicación
Restart=always – en caso de que la aplicación termine tratara de hacer el restart siempre
User – user owner
Group -group owner
Environment – variables de entorno disponibles para el servicio
[Install]
WantedBy – indica los targets bajo los cuales este servicio debe ser habilitado para iniciarse automáticamente al arrancar el sistema.
WantedBy=multi-user.target – indica que el sistema se encuentra en multiusuario sin entorno gráfico.(console)
Probando el Daemon para nuestro sitio web Go en Apache
Para que todo esto funcione debemos recargas systemd con el siguiente comando:
sudo systemctl daemon-reload
Bien, ¿y como corremos y detenemos el servicio a placer?
Recordemos que estamos usando systemd, por lo tanto, correr como parar el servicio estará regido por este
sudo systemctl stop mygoapp.service
sudo systemctl start mygoapp.service
En caso de que estés usando el codigo directamente en vez de un ejecutable, el valor ExecStart sería diferente ExecStart=/usr/local/go/bin/go run main.go