module_nginx.go 4.0 KB

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