├── haproxy ├── iptables-init.sh ├── iptables-remove.sh ├── Dockerfile ├── iptables-add.sh ├── run.sh ├── README.md ├── haproxy.cfg └── server.go /haproxy: -------------------------------------------------------------------------------- 1 | # Set ENABLED to 1 if you want the init script to start haproxy. 2 | ENABLED=1 3 | # Add extra flags here. 4 | #EXTRAOPTS="-de -m 16" 5 | -------------------------------------------------------------------------------- /iptables-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # enable 4 | echo 1 > /proc/sys/net/ipv4/ip_forward 5 | 6 | # reste 7 | iptables -F 8 | iptables -t nat -F 9 | -------------------------------------------------------------------------------- /iptables-remove.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | iptables -t nat -D OUTPUT -p tcp --dport 5910 -j REDIRECT --to-port 4910 3 | iptables -t nat -D PREROUTING -p tcp --dport 5910 -j REDIRECT --to-port 4910 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | ENV TERM linux 4 | RUN apt-get update -y 5 | RUN apt-get install haproxy golang tmux curl git iptables -y 6 | 7 | RUN mkdir /app 8 | WORKDIR /app 9 | ADD . /app/ 10 | 11 | ADD haproxy /etc/default/haproxy 12 | ADD haproxy.cfg /etc/haproxy/haproxy.cfg 13 | EXPOSE 9000 14 | -------------------------------------------------------------------------------- /iptables-add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | iptables -t nat -A OUTPUT -p tcp --dport 5910 -j REDIRECT --to-port 4910 3 | iptables -t nat -A PREROUTING -p tcp --dport 5910 -j REDIRECT --to-port 4910 4 | 5 | iptables -t nat -A OUTPUT -p tcp --dport 5911 -j REDIRECT --to-port 4911 6 | iptables -t nat -A PREROUTING -p tcp --dport 5911 -j REDIRECT --to-port 4911 7 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./iptables-init.sh 4 | ./iptables-add.sh 5 | 6 | session=forty9ten 7 | tmux new-session -ds "$session" 8 | 9 | tmux send-keys "service haproxy restart" "C-m" 10 | tmux send-keys "sleep 5 && while true; do curl localhost/v1/dowork; sleep 1; echo; done" "C-m" 11 | tmux split-window -h "go run /app/server.go -port 4910" 12 | tmux split-window -h "go run /app/server.go -port 4911" 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Install boot2docker (Mac or Windows) 2 | 3 | ``` 4 | https://github.com/boot2docker/boot2docker 5 | ``` 6 | 7 | # Open port for HAProxy dashboard 8 | 9 | skip this step if you are not using boot2docker 10 | 11 | ``` 12 | VBoxManage modifyvm "boot2docker-vm" --natpf1 "tcp-port9000,tcp,,9000,,9000"; 13 | VBoxManage modifyvm "boot2docker-vm" --natpf1 "udp-port9000,udp,,9000,,9000"; 14 | ``` 15 | 16 | # How to build: 17 | 18 | ``` 19 | docker build -rm --tag=multi-be-haproxy . 20 | ``` 21 | 22 | # How to run: 23 | 24 | ``` 25 | docker run -p :9000:9000 --privileged -i -t multi-be-haproxy /bin/bash 26 | ``` 27 | 28 | # Start HAProxy and backend apps 29 | 30 | ``` 31 | ./run.sh # pwd /app 32 | ``` 33 | 34 | The application runs inside tmux. Use the following command to connect to it. 35 | 36 | ``` 37 | tmux attach-session -t forty9ten 38 | ``` 39 | 40 | 41 | -------------------------------------------------------------------------------- /haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | log 127.0.0.1 local0 notice 3 | maxconn 2000 4 | user haproxy 5 | group haproxy 6 | 7 | defaults 8 | log global 9 | mode http 10 | option httplog 11 | option dontlognull 12 | retries 3 13 | option redispatch 14 | timeout connect 5000 15 | timeout client 10000 16 | timeout server 10000 17 | 18 | balance roundrobin 19 | option redispatch 20 | #option httpchk GET / HTTP/1.0 21 | 22 | frontend http 23 | bind :80 24 | default_backend srvs 25 | 26 | backend srvs 27 | server app1-forty9ten 127.0.0.1:4910 check port 5910 inter 2000 28 | server app2-forty9ten 127.0.0.1:4911 check port 5911 inter 2000 29 | 30 | server _app1-forty9ten 127.0.0.1:4910 check port 4910 inter 2000 backup 31 | server _app2-forty9ten 127.0.0.1:4911 check port 4911 inter 2000 backup 32 | 33 | listen stats :9000 34 | mode http 35 | stats enable 36 | stats hide-version 37 | stats realm Haproxy\ Statistics 38 | stats uri / 39 | stats auth forty9ten:changeme 40 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "net/http" 9 | ) 10 | 11 | var ( 12 | healthState = "UP" 13 | bindPort string 14 | ) 15 | 16 | func main() { 17 | var port = flag.String("port", "4910", "port") 18 | flag.Parse() 19 | 20 | bindPort = *port 21 | 22 | http.HandleFunc("/v1/health", health) 23 | http.HandleFunc("/v1/ping", ping) 24 | 25 | // toggling endpoints for testing only 26 | http.HandleFunc("/v1/down", down) 27 | http.HandleFunc("/v1/up", up) 28 | http.HandleFunc("/v1/pause", paused) 29 | 30 | // similate work being done 31 | http.HandleFunc("/v1/dowork", dowork) 32 | 33 | fmt.Printf("Server up and running on port %s\n", bindPort) 34 | http.ListenAndServe(fmt.Sprintf(":%s", bindPort), nil) 35 | } 36 | 37 | func ping(w http.ResponseWriter, req *http.Request) { 38 | w.Write([]byte("OK")) 39 | w.WriteHeader(200) 40 | } 41 | 42 | func health(w http.ResponseWriter, req *http.Request) { 43 | w.Write([]byte(healthState)) 44 | w.WriteHeader(200) 45 | } 46 | 47 | func dowork(w http.ResponseWriter, req *http.Request) { 48 | switch { 49 | case healthState == "UP": 50 | w.Write([]byte("DOING SOME WORK. RUNNING ON PORT: " + bindPort)) 51 | w.WriteHeader(200) 52 | case healthState == "PAUSE": 53 | http.Error(w, "PAUSED", 503) 54 | } 55 | } 56 | 57 | func down(w http.ResponseWriter, req *http.Request) { 58 | os.Exit(-1) 59 | } 60 | 61 | func up(w http.ResponseWriter, req *http.Request) { 62 | healthState = "UP" 63 | } 64 | 65 | func paused(w http.ResponseWriter, req *http.Request) { 66 | healthState = "PAUSE" 67 | } 68 | --------------------------------------------------------------------------------