Si estás interesado por los contenedores (concretamente por Docker) y estás inmerso en el mundo de Go, entonces es probable que te hayas preguntado cómo puedes dockerizar tu aplicación. Y aquí estamos para explicártelo, a la vez que repasamos algunos conceptos básicos y buenas prácticas de Go.
Por suerte, el proceso de dockerizar una aplicación escrita en Go es muy sencillo, pues, conceptualmente, lo único que tenemos que hacer es compilar nuestra aplicación para generar el binario que irá dentro del contenedor.
Compilando nuestra aplicación Go
Para este artículo vamos a hacer un par de asunciones:
- Que el punto de entrada de nuestra aplicación Go está en el path
cmd/main.go
. - Que el Dockerfile estará en la raíz del proyecto.
Para compilar nuestra aplicación, vamos a usar la imagen oficial de Go, en concreto, el tag de alpine
. Eso puede ser así siempre y cuándo la compilación de nuestra aplicación no tenga algún requisito específico por el cuál tengamos que hacer uso de otro tag.
Además, por simplicidad, vamos a usar la última versión de la imagen (latest), cosa bastante recomendable en Go, pero, si fuera necesario, podríamos especificar una imagen en concreto.
FROM golang:alpine
Lo siguiente será definir el directorio de trabajo (WORKDIR
), dónde incluiremos el código de nuestra aplicación. Para ello vamos a hacer uso del comando COPY
(en lugar del comando ADD
que mucha gente utiliza de manera errónea), tal y cómo nos recomiendan desde Docker.
WORKDIR /go/src/myapp
COPY . .
Para esta ocasión, hemos usado un path de aplicación genérico (myapp
), pero podríamos usar el correspondiente a nuestra aplicación, por ejemplo: github.com/friendsofgo/graphiql
.
Finalmente, solo faltará compilar nuestra aplicación, dejando nuestro binario en el directorio bin
del $GOPATH
, por ejemplo.
RUN go build -o /go/bin/myapp cmd/main.go
De modo que ya tendríamos un Dockerfile con una pinta similar a esta:
FROM golang:alpine
WORKDIR /go/src/myapp
COPY . .
RUN go build -o /go/bin/myapp cmd/main.go
Creando una imagen mínima
Ahora mismo, la imagen que hemos creado hasta este momento, podria servir cómo la imagen de nuestra aplicación. Sin embargo, cómo también suelen recomendar desde Docker, conviene hacer que nuestras imágenes sean mínimas. En este caso, cómo estamos hablando de una aplicación compilada, será suficiente con crear una imagen que contenga el binario.
En el ejemplo que estamos viendo, la imagen generada hasta el momento es bastante pequeña, pero, podría ser que, para el proceso de compilación, tuviéramos que instalar otras dependencias cómo dep o glide, cuya presencia no tiene mucho sentido en una hipotética imagen definitiva.
Para ello vamos a hacer uso de Docker multi-stage builds, para lo que hace falta la versión de Docker 17.05 o superior.
El primer paso será modificar, ligeramente, la primera línea de nuestro Dockerfile:
FROM golang:alpine AS build
Posteriormente vamos a crear una nueva imagen mínima (scratch
) en el mismo Dockerfile
, que sólo contenga el binario generado en el proceso de compilación anterior:
FROM scratch
COPY --from=build /go/bin/myapp /go/bin/myapp
ENTRYPOINT ["/go/bin/myapp"]
Cómo podemos ver, estamos haciendo que nuestro punto de entrada (ENTRYPOINT
) sea el binario generado, además, estamos habilitando el paso de parámetros en la ejecución de contenedores con nuestra imagen, parámetros que posteriormente podríamos capturar, por ejemplo, haciendo uso de los flags nativos de Go.
Al final, deberíamos tener un Dockerfile parecido a éste:
FROM golang:alpine AS build
WORKDIR /go/src/myapp
COPY . .
RUN go build -o /go/bin/myapp cmd/main.go
FROM scratch
COPY --from=build /go/bin/myapp /go/bin/myapp
ENTRYPOINT ["/go/bin/myapp"]
¡Y ahora ya sí! Ya tendríamos nuestra aplicación correctamente dockerizada, con una imagen mínima que tiene exclusivamente el binario de nuestra aplicación.
Predicando con el ejemplo
Es bien sabido que, un buen maestro, debe predicar con el ejemplo. Es por eso que, en nuestro caso, hemos aprovechado la redacción de éste artículo para dockerizar nuestra aplicación de GraphiQL. Así que, no dudes en echar un vistazo a nuestro Dockerfile a modo de ejemplo ni en comentar con nosotros cualquier duda que te surja durante el proceso de dockerización de tus aplicaciones.
Ahora es tu turno, te toca a ti experimentar en primera persona.