From 6711eaf20aa1bbb6452b0e1b869475ae161d86d6 Mon Sep 17 00:00:00 2001 From: Juan Camargo Date: Fri, 30 Jul 2021 19:55:11 -0300 Subject: [PATCH 1/6] Fix dokcer-compose.yaml networks, service names, hostname/container_name, ports and depends_on --- docker-compose.yaml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index e196b36..dca02a6 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,6 +2,8 @@ version: "3.9" services: web: build: services/frontend + hostname: frontend + container_name: frontend ports: - "5000:5000" networks: @@ -9,18 +11,33 @@ services: - backend reader: build: services/reader + hostname: reader + container_name: reader ports: - - "8081:8081" + - "8080:8080" + depends_on: + - redis networks: - - frontend + - backend writer: build: services/writer + hostname: writer + container_name: writer ports: - - "8080:8080" + - "8081:8081" + depends_on: + - redis networks: - backend - reids: + redis: image: "redis:alpine" + hostname: redis + container_name: redis + ports: + - "6379:6379" + networks: + - backend networks: backend: + frontend: From f45978e0949bdac9a82a2ea087dbe95ba42a27b6 Mon Sep 17 00:00:00 2001 From: Juan Camargo Date: Fri, 30 Jul 2021 19:57:12 -0300 Subject: [PATCH 2/6] Fix frontend Dockerfile --- services/frontend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/frontend/Dockerfile b/services/frontend/Dockerfile index 2e3c45c..d1112a4 100644 --- a/services/frontend/Dockerfile +++ b/services/frontend/Dockerfile @@ -1,6 +1,6 @@ FROM node:latest WORKDIR /app -ADD . . +ADD . /app RUN npm install -g serve EXPOSE 5000 CMD "serve" \ No newline at end of file From a659686571b22f4a5f3f28f2f6adb3f5d2f6b4ff Mon Sep 17 00:00:00 2001 From: Juan Camargo Date: Fri, 30 Jul 2021 19:57:27 -0300 Subject: [PATCH 3/6] Fix reader Dockerfile --- services/reader/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/services/reader/Dockerfile b/services/reader/Dockerfile index 90d2094..23b8c64 100644 --- a/services/reader/Dockerfile +++ b/services/reader/Dockerfile @@ -1,6 +1,7 @@ FROM golang:1.16 WORKDIR /go/src/github.com/PicPay/picpay-jr-devops-challenge/services/go ADD . /go/src/github.com/PicPay/picpay-jr-devops-challenge/services/go - +RUN go mod download +RUN go build -o main . EXPOSE 8080 -CMD ["go","run","main.go"] \ No newline at end of file +CMD ["/go/src/github.com/PicPay/picpay-jr-devops-challenge/services/go/main"] \ No newline at end of file From b82af24b91dca5f1d93c28c8b690a9f2a387037d Mon Sep 17 00:00:00 2001 From: Juan Camargo Date: Fri, 30 Jul 2021 19:58:02 -0300 Subject: [PATCH 4/6] Fix Go application - redis return --- services/reader/main.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/services/reader/main.go b/services/reader/main.go index cdb732d..9b6d87e 100644 --- a/services/reader/main.go +++ b/services/reader/main.go @@ -24,8 +24,11 @@ func main() { mux.HandleFunc("/data", func(writer http.ResponseWriter, request *http.Request) { client := redis.NewClient(&redis.Options{Addr: redis_host+":"+redis_port}) - key := client.Get(client.Context(),"SHAREDKEY") - fmt.Fprintf(writer, key.Val()) + key, err := client.Get("SHAREDKEY").Result() + if err != nil { + panic(err) + } + fmt.Fprintf(writer, key) }) handler := cors.New(cors.Options{ From 95cfd3926c3c0f230125e0a0c8ce09dd05af4182 Mon Sep 17 00:00:00 2001 From: Juan Camargo Date: Fri, 30 Jul 2021 19:58:15 -0300 Subject: [PATCH 5/6] Fix writer Dockerfile --- services/writer/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/writer/Dockerfile b/services/writer/Dockerfile index abc40b4..f4873df 100644 --- a/services/writer/Dockerfile +++ b/services/writer/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.9 WORKDIR /app ADD . /app +RUN pip install redis EXPOSE 8081 -CMD ["python"] -ENTRYPOINT ["main.py"] \ No newline at end of file +CMD [ "python", "./main.py" ] \ No newline at end of file From 52c1054d21734cc51bd3b1ac6ab746d8167ca0a3 Mon Sep 17 00:00:00 2001 From: Juan Camargo Date: Fri, 30 Jul 2021 19:58:44 -0300 Subject: [PATCH 6/6] Readme, chart and Makefile --- Makefile | 14 ++++++++++++++ README_JUAN.md | 36 ++++++++++++++++++++++++++++++++++++ chart.png | Bin 0 -> 16585 bytes 3 files changed, 50 insertions(+) create mode 100644 Makefile create mode 100644 README_JUAN.md create mode 100644 chart.png diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6225df --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +.PHONY: all up down + +all: up + +up: + cd services/reader && \ + go mod init github.com/PicPay/picpay-jr-devops-challenge/services/go && \ + go get ./... && \ + docker-compose up -d --build + +down: + cd services/reader && \ + rm -f go.mod go.sum && \ + docker-compose down \ No newline at end of file diff --git a/README_JUAN.md b/README_JUAN.md new file mode 100644 index 0000000..e54a261 --- /dev/null +++ b/README_JUAN.md @@ -0,0 +1,36 @@ +# Docker Compose +- Nome "redis" estava errado +- Adicionar a network ```frontend``` +- Resolver network dos serviços +- Aadicionar ```hostname``` e ```container_name``` +- Resolver portas iguais pelos containers +- Adicionar ```depends_on``` para assegurar o funcionamento das aplicações + +# Frontend +- Dockerfile - Adicionar ```ADD . /app``` + +# Writer +- Dockerfile - Instalar dependencia do redis ```RUN pip install redis``` +- Dockerfile - Trocar comando inicial ```CMD [ "python", "./main.py" ]``` + +# Reader +- Gerar os requisitos com ```go mod init``` e ```go get ./...``` (feito automaticamente com o Makefile) +- Dockerfile - Instalar modulos ```RUN go mod download``` +- Dockerfile - Gerar o executavel ```RUN go build -o main .``` +- Dockerfile - Executar o arquivo gerado ```CMD ["/go/src/github.com/PicPay/picpay-jr-devops-challenge/services/go/main"]``` + +## Reader -Aplicação - Erro ao pegar o valor no Redis, resolvido com ajustes no código: +``` +key, err := client.Get("SHAREDKEY").Result() +if err != nil { + panic(err) +} +fmt.Fprintf(writer, key) +``` + +# Usage +- Subir os serviços ```make up``` +- Matar os serviços ```make down``` + +# Chart +![Organograma](https://i.imgur.com/kPxydAv.png "Organograma") \ No newline at end of file diff --git a/chart.png b/chart.png new file mode 100644 index 0000000000000000000000000000000000000000..b3c406bc2bba54b86ec5e2ab956c73331d6cdf07 GIT binary patch literal 16585 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 V70&Jge