Integracion continue con Travis CI y Docker

2019-05-01 | Gabriel Garrido | 4 min de lectura
Share:
On this page
  1. Introducción
  2. Primero lo primero
  3. Aplicación
  4. Docker
  5. Travis
  6. Juntando todo
  7. Notas finales
  8. Errata

Apoya este blog

Si te resulta util este contenido, considera apoyar el blog.

travis

Introducción#

En este artículo veremos cómo crear un proceso simple de integración continua utilizando Github, Travis-CI y Docker HUB. Los archivos utilizados aquí se pueden encontrar AQUÍ. En el próximo artículo continuaremos con lo que tenemos aquí para proporcionar despliegue continuo, posiblemente usando Jenkins o quizás Travis. Hazme saber cuál prefieres ver.

Primero lo primero#
Aplicación#

Revisaremos el archivo docker, el código de la aplicación y el archivo travis-ci, así que comencemos con la aplicación main.go:

package main

import (
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"strconv"
)

func httphandler(w http.ResponseWriter, r *http.Request) {
	ipAddress, _, _ := net.SplitHostPort(r.RemoteAddr)
	fmt.Fprintf(w, "%s", ipAddress)
}

func main() {
	port, err := strconv.Atoi(os.Getenv("WHATISMYIP_PORT"))
	if err != nil {
		log.Fatalf("Please make sure the environment variable WHATISMYIP_PORT is defined and is a valid integer [1024-65535], error: %s", err)
	}

	listener := fmt.Sprintf(":%d", port)

	http.HandleFunc("/", httphandler)
	log.Fatal(http.ListenAndServe(listener, nil))
}

Revisemos rápidamente lo que hace este código. Primero verificamos el puerto a utilizar, luego lo convertimos en un número, registramos el manejador para nuestra función HTTP y escuchamos las solicitudes. Este código imprimirá nuestra dirección IP como se esperaría por el nombre.

Luego el código de main_test.go:

package main

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestHandler(t *testing.T) {
	req, err := http.NewRequest("GET", "/", nil)
	if err != nil {
		t.Fatal(err)
	}

	rr := httptest.NewRecorder()
	handler := http.HandlerFunc(httphandler)

	handler.ServeHTTP(rr, req)

	if status := rr.Code; status != http.StatusOK {
		t.Errorf("Status code got: %v want %v",
			status, http.StatusOK)
	}

	expected := ``
	if rr.Body.String() != expected {
		t.Errorf("Unexpected body got: %v want %v",
			rr.Body.String(), expected)
	}
}

La prueba es bastante simple, solo verifica que el servidor web funcione al intentar acceder a / y comprobando que el cuerpo esté vacío y el código de estado sea 200.

Docker#

A continuación, el Dockerfile:

FROM golang:1.12-alpine

LABEL maintainer="[email protected]"

# Set the Current Working Directory inside the container
WORKDIR $GOPATH/src/github.com/kainlite/whatismyip-go
COPY . .

# Download all the dependencies
# https://stackoverflow.com/questions/28031603/what-do-three-dots-mean-in-go-command-line-invocations
RUN go get -d -v ./...

# Install the package and create test binary
RUN go install -v ./... && \
    CGO_ENABLED=0 GOOS=linux go test -c

# This container exposes port 8080 to the outside world
EXPOSE 8000

# Set default environment variable values
ENV WHATISMYIP_PORT 8000

# Perform any further action as an unprivileged user.
USER nobody:nobody

# Run the executable
CMD ["whatismyip-go"]

Configuramos el directorio de trabajo para satisfacer a go, luego obtenemos las dependencias e instalamos nuestro binario. También generamos un binario de prueba, exponemos el puerto que queremos utilizar y configuramos el usuario como nobody en caso de que alguien pueda explotar nuestra aplicación y acceder al contenedor. Finalmente, establecemos el comando a ejecutar en docker run.

Travis#

Y por último, pero no menos importante, el archivo .travis.yml:

language: go

services:
  - docker

before_install:
- docker build --no-cache -t ${TRAVIS_REPO_SLUG}:${TRAVIS_COMMIT} .
- docker run ${TRAVIS_REPO_SLUG}:${TRAVIS_COMMIT} /go/src/github.com/kainlite/whatismyip-go/whatismyip-go.test
- docker run -d -p 127.0.0.1:8000:8000 ${TRAVIS_REPO_SLUG}:${TRAVIS_COMMIT}

script:
  - curl 127.0.0.1:8000
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
  - docker push ${TRAVIS_REPO_SLUG}:${TRAVIS_COMMIT}

Le indicamos a Travis que ejecutaremos código Go y Docker. Luego, construimos la imagen, ejecutamos las pruebas y después la aplicación como parte de la inicialización. Después de eso, validamos que la aplicación funcione y, por último, iniciamos sesión en Docker Hub y subimos la imagen. Las cosas importantes a tener en cuenta aquí son que usamos variables, por ejemplo, el nombre del repositorio, el SHA del commit, y el nombre de usuario y contraseña de Docker de manera segura, ya que Travis-CI oculta los valores que le indicamos.

Juntando todo#

Hasta ahora, tenemos el repositorio funcionando, la configuración de Travis, el Dockerfile y la aplicación, pero ahora necesitamos usarlo. Necesitarás crear una cuenta de Travis para que esto funcione, luego vincula tu cuenta de GitHub con Travis. Podrás sincronizar tus repositorios y deberías ver algo como esto: image Una vez que tu cuenta esté vinculada, podrás sincronizar y habilitar los repositorios para que se construyan.

Después de habilitar el repositorio, puedes configurar algunos detalles como variables de entorno. Aquí estableceremos las credenciales para Docker Hub. image

Y ahora crearemos el repositorio en Docker Hub: image Después de que se crea el repositorio, podemos activar una compilación desde Travis o enviar un commit al repositorio para activar una compilación y validar que todo funciona.

Deberías ver algo como esto en Travis si todo salió bien: image Puedes validar que todo salió bien revisando el SHA del commit que activó la compilación.

Y en Docker Hub: image El mismo SHA se utilizará para etiquetar la imagen.

Notas finales#

Publicaré algunos artículos sobre CI y CD, y buenas prácticas que los DevOps/SRE deberían tener en cuenta: consejos, trucos y ejemplos completos de despliegue. Esta es la primera parte de una posible serie de dos o tres artículos con un ejemplo básico pero completo de CI primero y luego CD. Esto, por supuesto, puede cambiar, y cualquier comentario será muy apreciado :).

Algunos enlaces útiles para Travis y Docker y la lista de variables de entorno que se pueden usar.

Errata#

Si encuentras algún error o tienes alguna sugerencia, por favor envíame un mensaje para que se corrija.



$ Comentarios

Online: 0

Por favor inicie sesión para poder escribir comentarios.

2019-05-01 | Gabriel Garrido