github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/cmd/puppeth/module_nginx.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package main 13 14 import ( 15 "bytes" 16 "fmt" 17 "html/template" 18 "math/rand" 19 "path/filepath" 20 "strconv" 21 22 "github.com/Sberex/go-sberex/log" 23 ) 24 25 // nginxDockerfile is theis the Dockerfile required to build an nginx reverse- 26 // proxy. 27 var nginxDockerfile = `FROM jwilder/nginx-proxy` 28 29 // nginxComposefile is the docker-compose.yml file required to deploy and maintain 30 // an nginx reverse-proxy. The proxy is responsible for exposing one or more HTTP 31 // services running on a single host. 32 var nginxComposefile = ` 33 version: '2' 34 services: 35 nginx: 36 build: . 37 image: {{.Network}}/nginx 38 ports: 39 - "{{.Port}}:80" 40 volumes: 41 - /var/run/docker.sock:/tmp/docker.sock:ro 42 logging: 43 driver: "json-file" 44 options: 45 max-size: "1m" 46 max-file: "10" 47 restart: always 48 ` 49 50 // deployNginx deploys a new nginx reverse-proxy container to expose one or more 51 // HTTP services running on a single host. If an instance with the specified 52 // network name already exists there, it will be overwritten! 53 func deployNginx(client *sshClient, network string, port int, nocache bool) ([]byte, error) { 54 log.Info("Deploying nginx reverse-proxy", "server", client.server, "port", port) 55 56 // Generate the content to upload to the server 57 workdir := fmt.Sprintf("%d", rand.Int63()) 58 files := make(map[string][]byte) 59 60 dockerfile := new(bytes.Buffer) 61 template.Must(template.New("").Parse(nginxDockerfile)).Execute(dockerfile, nil) 62 files[filepath.Join(workdir, "Dockerfile")] = dockerfile.Bytes() 63 64 composefile := new(bytes.Buffer) 65 template.Must(template.New("").Parse(nginxComposefile)).Execute(composefile, map[string]interface{}{ 66 "Network": network, 67 "Port": port, 68 }) 69 files[filepath.Join(workdir, "docker-compose.yaml")] = composefile.Bytes() 70 71 // Upload the deployment files to the remote server (and clean up afterwards) 72 if out, err := client.Upload(files); err != nil { 73 return out, err 74 } 75 defer client.Run("rm -rf " + workdir) 76 77 // Build and deploy the reverse-proxy service 78 if nocache { 79 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s build --pull --no-cache && docker-compose -p %s up -d --force-recreate", workdir, network, network)) 80 } 81 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s up -d --build --force-recreate", workdir, network)) 82 } 83 84 // nginxInfos is returned from an nginx reverse-proxy status check to allow 85 // reporting various configuration parameters. 86 type nginxInfos struct { 87 port int 88 } 89 90 // Report converts the typed struct into a plain string->string map, containing 91 // most - but not all - fields for reporting to the user. 92 func (info *nginxInfos) Report() map[string]string { 93 return map[string]string{ 94 "Shared listener port": strconv.Itoa(info.port), 95 } 96 } 97 98 // checkNginx does a health-check against an nginx reverse-proxy to verify whether 99 // it's running, and if yes, gathering a collection of useful infos about it. 100 func checkNginx(client *sshClient, network string) (*nginxInfos, error) { 101 // Inspect a possible nginx container on the host 102 infos, err := inspectContainer(client, fmt.Sprintf("%s_nginx_1", network)) 103 if err != nil { 104 return nil, err 105 } 106 if !infos.running { 107 return nil, ErrServiceOffline 108 } 109 // Container available, assemble and return the useful infos 110 return &nginxInfos{ 111 port: infos.portmap["80/tcp"], 112 }, nil 113 }