mirror of
https://github.com/bingohuang/docker-labs.git
synced 2025-07-14 01:57:32 +08:00
parent
7df7a7c68f
commit
a4b0a98df3
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
play-with-docker
|
||||
node_modules
|
||||
|
||||
pwd/*
|
||||
|
@ -2,12 +2,17 @@ package config
|
||||
|
||||
import "flag"
|
||||
|
||||
var SSLPortNumber, PortNumber, Key, Cert string
|
||||
var SSLPortNumber, PortNumber, Key, Cert, SessionsFile, PWDContainerName, PWDCName string
|
||||
var MaxLoadAvg float64
|
||||
|
||||
func ParseFlags() {
|
||||
flag.StringVar(&PortNumber, "port", "3000", "Give a TCP port to run the application")
|
||||
flag.StringVar(&SSLPortNumber, "sslPort", "3001", "Give a SSL TCP port")
|
||||
flag.StringVar(&Key, "key", "./pwd/server-key.pem", "Server key for SSL")
|
||||
flag.StringVar(&Cert, "cert", "./pwd/server.pem", "Give a SSL cert")
|
||||
flag.StringVar(&SessionsFile, "save", "./pwd/sessions", "Tell where to store sessions file")
|
||||
flag.StringVar(&PWDContainerName, "name", "pwd", "Container name used to run PWD (used to be able to connect it to the networks it creates)")
|
||||
flag.StringVar(&PWDCName, "cname", "host1", "CNAME given to this host")
|
||||
flag.Float64Var(&MaxLoadAvg, "maxload", 100, "Maximum allowed load average before failing ping requests")
|
||||
flag.Parse()
|
||||
}
|
||||
|
@ -1,16 +1,35 @@
|
||||
version: '2'
|
||||
services:
|
||||
pwd:
|
||||
haproxy:
|
||||
container_name: proxy
|
||||
image: haproxy
|
||||
ports:
|
||||
- "80:8080"
|
||||
- "443:8443"
|
||||
|
||||
volumes:
|
||||
- ./haproxy:/usr/local/etc/haproxy
|
||||
pwd1:
|
||||
# pwd daemon container always needs to be named this way
|
||||
container_name: pwd
|
||||
container_name: pwd1
|
||||
# use the latest golang image
|
||||
image: golang
|
||||
# go to the right place and starts the app
|
||||
command: /bin/sh -c 'cd /go/src/github.com/franela/play-with-docker; go run api.go'
|
||||
ports:
|
||||
# app exposes port 3000
|
||||
- "80:3000"
|
||||
- "443:3001"
|
||||
command: /bin/sh -c 'cd /go/src/github.com/franela/play-with-docker; go run api.go -save ./pwd/sessions1 -name pwd1 -cname host1'
|
||||
volumes:
|
||||
# since this app creates networks and launches containers, we need to talk to docker daemon
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
# mount the box mounted shared folder to the container
|
||||
- $GOPATH/src:/go/src
|
||||
environment:
|
||||
GOOGLE_RECAPTCHA_DISABLED: "true"
|
||||
pwd2:
|
||||
# pwd daemon container always needs to be named this way
|
||||
container_name: pwd2
|
||||
# use the latest golang image
|
||||
image: golang
|
||||
# go to the right place and starts the app
|
||||
command: /bin/sh -c 'cd /go/src/github.com/franela/play-with-docker; go run api.go -save ./pwd/sessions2 -name pwd2 -cname host2'
|
||||
volumes:
|
||||
# since this app creates networks and launches containers, we need to talk to docker daemon
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
@ -2,7 +2,6 @@ package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/franela/play-with-docker/services"
|
||||
@ -12,7 +11,6 @@ import (
|
||||
func GetSession(rw http.ResponseWriter, req *http.Request) {
|
||||
vars := mux.Vars(req)
|
||||
sessionId := vars["sessionId"]
|
||||
log.Println(sessionId)
|
||||
|
||||
session := services.GetSession(sessionId)
|
||||
|
||||
|
@ -1,13 +1,20 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/franela/play-with-docker/config"
|
||||
"github.com/franela/play-with-docker/services"
|
||||
)
|
||||
|
||||
type NewSessionResponse struct {
|
||||
SessionId string `json:"session_id"`
|
||||
Hostname string `json:"hostname"`
|
||||
}
|
||||
|
||||
func NewSession(rw http.ResponseWriter, req *http.Request) {
|
||||
req.ParseForm()
|
||||
if !services.IsHuman(req) {
|
||||
@ -25,11 +32,15 @@ func NewSession(rw http.ResponseWriter, req *http.Request) {
|
||||
log.Println(err)
|
||||
//TODO: Return some error code
|
||||
} else {
|
||||
|
||||
hostname := fmt.Sprintf("%s.%s", config.PWDCName, req.Host)
|
||||
// If request is not a form, return sessionId in the body
|
||||
if req.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||
rw.Write([]byte(s.Id))
|
||||
resp := NewSessionResponse{SessionId: s.Id, Hostname: hostname}
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(rw).Encode(resp)
|
||||
return
|
||||
}
|
||||
http.Redirect(rw, req, fmt.Sprintf("/p/%s", s.Id), http.StatusFound)
|
||||
http.Redirect(rw, req, fmt.Sprintf("http://%s/p/%s", hostname, s.Id), http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,23 @@
|
||||
package handlers
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/franela/play-with-docker/config"
|
||||
"github.com/shirou/gopsutil/load"
|
||||
)
|
||||
|
||||
func Ping(rw http.ResponseWriter, req *http.Request) {
|
||||
// Get system load average of the last 5 minutes and compare it against a threashold.
|
||||
|
||||
a, err := load.Avg()
|
||||
if err != nil {
|
||||
log.Println("Cannot get system load average!", err)
|
||||
} else {
|
||||
if a.Load5 > config.MaxLoadAvg {
|
||||
log.Printf("System load average is too high [%f]\n", a.Load5)
|
||||
rw.WriteHeader(http.StatusInsufficientStorage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
haproxy/haproxy.cfg
Normal file
32
haproxy/haproxy.cfg
Normal file
@ -0,0 +1,32 @@
|
||||
defaults
|
||||
mode http
|
||||
timeout connect 5000ms
|
||||
timeout client 50000ms
|
||||
timeout server 50000ms
|
||||
|
||||
frontend http-in
|
||||
bind *:8080
|
||||
|
||||
acl host_localhost hdr(host) localhost
|
||||
acl host_pwd1 hdr_reg(host) -i ^.*\.?host1\.localhost$
|
||||
acl host_pwd2 hdr_reg(host) -i ^.*\.?host2\.localhost$
|
||||
|
||||
use_backend all if host_localhost
|
||||
use_backend pwd1 if host_pwd1
|
||||
use_backend pwd2 if host_pwd2
|
||||
|
||||
backend all
|
||||
balance roundrobin
|
||||
|
||||
option httpchk GET /ping HTTP/1.0
|
||||
http-check expect rstatus 200
|
||||
default-server inter 3s fall 3 rise 2
|
||||
|
||||
server node1 pwd1:3000 check
|
||||
server node2 pwd2:3000 check
|
||||
|
||||
backend pwd1
|
||||
server node1 pwd1:3000
|
||||
|
||||
backend pwd2
|
||||
server node2 pwd2:3000
|
1
pwd/.gitignore
vendored
1
pwd/.gitignore
vendored
@ -1 +0,0 @@
|
||||
sessions.gob
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/franela/play-with-docker/config"
|
||||
"github.com/googollee/go-socket.io"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/twinj/uuid"
|
||||
@ -241,13 +242,13 @@ func NewSession(duration time.Duration) (*Session, error) {
|
||||
log.Printf("Network [%s] created for session [%s]\n", s.Id, s.Id)
|
||||
|
||||
// Connect PWD daemon to the new network
|
||||
ip, err := ConnectNetwork("pwd", s.Id, "")
|
||||
ip, err := ConnectNetwork(config.PWDContainerName, s.Id, "")
|
||||
if err != nil {
|
||||
log.Println("ERROR NETWORKING")
|
||||
return nil, err
|
||||
}
|
||||
s.PwdIpAddress = ip
|
||||
log.Printf("Connected pwd to network [%s]\n", s.Id)
|
||||
log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id)
|
||||
|
||||
// Schedule peridic tasks execution
|
||||
s.SchedulePeriodicTasks()
|
||||
@ -290,7 +291,7 @@ func setGauges() {
|
||||
}
|
||||
|
||||
func LoadSessionsFromDisk() error {
|
||||
file, err := os.Open("./pwd/sessions.gob")
|
||||
file, err := os.Open(config.SessionsFile)
|
||||
if err == nil {
|
||||
decoder := gob.NewDecoder(file)
|
||||
err = decoder.Decode(&sessions)
|
||||
@ -322,7 +323,7 @@ func LoadSessionsFromDisk() error {
|
||||
if s.PwdIpAddress == "" {
|
||||
log.Fatal("Cannot load stored sessions as they don't have the pwd ip address stored with them")
|
||||
}
|
||||
if _, err := ConnectNetwork("pwd", s.Id, s.PwdIpAddress); err != nil {
|
||||
if _, err := ConnectNetwork(config.PWDContainerName, s.Id, s.PwdIpAddress); err != nil {
|
||||
if strings.Contains(err.Error(), "Could not attach to network") {
|
||||
log.Printf("Network for session [%s] doesn't exist. Removing all instances and session.", s.Id)
|
||||
CloseSession(s)
|
||||
@ -331,7 +332,7 @@ func LoadSessionsFromDisk() error {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Printf("Connected pwd to network [%s]\n", s.Id)
|
||||
log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id)
|
||||
|
||||
// Schedule peridic tasks execution
|
||||
s.SchedulePeriodicTasks()
|
||||
@ -346,7 +347,7 @@ func LoadSessionsFromDisk() error {
|
||||
func saveSessionsToDisk() error {
|
||||
rw.Lock()
|
||||
defer rw.Unlock()
|
||||
file, err := os.Create("./pwd/sessions.gob")
|
||||
file, err := os.Create(config.SessionsFile)
|
||||
if err == nil {
|
||||
encoder := gob.NewEncoder(file)
|
||||
err = encoder.Encode(&sessions)
|
||||
|
Loading…
x
Reference in New Issue
Block a user