Skip to content

Commit 0d37367

Browse files
committed
fix: #10 with new health check (internal)
1 parent c089a0c commit 0d37367

1 file changed

Lines changed: 79 additions & 64 deletions

File tree

go/socket-proxy/main.go

Lines changed: 79 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package main
22

33
import(
4-
"log"
54
"net"
65
"net/http"
76
"net/url"
@@ -13,68 +12,66 @@ import(
1312
"sync"
1413
"regexp"
1514
"strconv"
16-
"flag"
1715
"time"
16+
17+
"github.com/11notes/go"
1818
)
1919

2020
var(
21+
Eleven eleven.New = eleven.New{}
2122
proxy *httputil.ReverseProxy
2223
socket net.Listener
2324
wg sync.WaitGroup
2425
socketProxy string
25-
dockerSocket *net.Conn
26+
keepAlive string = os.Getenv("SOCKET_PROXY_KEEPALIVE")
27+
timeout string = os.Getenv("SOCKET_PROXY_TIMEOUT")
28+
uid string = os.Getenv("SOCKET_PROXY_UID")
29+
gid string = os.Getenv("SOCKET_PROXY_GID")
30+
volume string = os.Getenv("SOCKET_PROXY_VOLUME")
31+
dockerSocket string = os.Getenv("SOCKET_PROXY_DOCKER_SOCKET")
2632
)
2733

28-
func signals(){
29-
signalChannel := make(chan os.Signal, 1)
30-
signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT)
31-
go func() {
32-
<-signalChannel
33-
os.Exit(0)
34-
}()
35-
}
36-
3734
func prepareFileSystemDropPrivileges(){
3835
// unprivileged user
39-
proxyUID, err := strconv.Atoi(os.Getenv("SOCKET_PROXY_UID"))
36+
proxyUID, err := strconv.Atoi(uid)
4037
if err != nil {
41-
log.Fatalf("SOCKET_PROXY_UID must be a number %v", err)
38+
Eleven.LogFatal("SOCKET_PROXY_UID must be a number %v", err)
4239
}
43-
proxyGID, err := strconv.Atoi(os.Getenv("SOCKET_PROXY_GID"))
40+
proxyGID, err := strconv.Atoi(gid)
4441
if err != nil {
45-
log.Fatalf("SOCKET_PROXY_GID must be a number %v", err)
42+
Eleven.LogFatal("SOCKET_PROXY_GID must be a number %v", err)
4643
}
47-
proxyVolume := regexp.MustCompile(`/+$`).ReplaceAllString(os.Getenv("SOCKET_PROXY_VOLUME"), "")
44+
proxyVolume := regexp.MustCompile(`/+$`).ReplaceAllString(volume, "")
4845

4946
// chown file system for unprivileged user
5047
if err := os.Chown(proxyVolume, proxyUID , proxyGID); err != nil {
51-
log.Fatalf("could not chown folder %s", proxyVolume, err)
48+
Eleven.LogFatal("could not chown folder %s", proxyVolume, err)
5249
}
5350

5451
// check docker socket permissions
55-
stat, err := os.Stat(os.Getenv("SOCKET_PROXY_DOCKER_SOCKET"))
52+
stat, err := os.Stat(dockerSocket)
5653
if err != nil {
57-
log.Fatalf("could not evaluate ownership of docker socket, permission issue %v", err)
54+
Eleven.LogFatal("could not evaluate ownership of docker socket, permission issue %v", err)
5855
}
5956
if ownership, ok := stat.Sys().(*syscall.Stat_t); !ok {
60-
log.Fatalf("could not evaluate ownership of docker socket, permission issue %v", err)
57+
Eleven.LogFatal("could not evaluate ownership of docker socket, permission issue %v", err)
6158
}else{
6259
if(int(ownership.Uid) != os.Getuid()){
63-
log.Fatalf("can’t access docker socket as UID %d owned by UID %d\nplease change the user setting in your compose to the correct UID/GID pair like this:\nservices:\n socket-proxy:\n user: \"%d:%d\"", os.Getuid(), ownership.Uid, ownership.Uid, ownership.Gid)
60+
Eleven.LogFatal("can’t access docker socket as UID %d owned by UID %d. Please change the user setting in your compose to the correct UID/GID pair like this >> user: %d:%d", os.Getuid(), ownership.Uid, ownership.Uid, ownership.Gid)
6461
}else{
6562
if(int(ownership.Gid) != os.Getgid()){
66-
log.Fatalf("can’t access docker socket as GID %d owned by GID %d\nplease change the user setting in your compose to the correct UID/GID pair like this:\nservices:\n socket-proxy:\n user: \"%d:%d\"", os.Getgid(), ownership.Gid, os.Getuid(), ownership.Gid)
63+
Eleven.LogFatal("can’t access docker socket as GID %d owned by GID %d. Please change the user setting in your compose to the correct UID/GID pair like this >> user: %d:%d", os.Getgid(), ownership.Gid, os.Getuid(), ownership.Gid)
6764
}
6865
}
6966
}
7067

7168
// drop privileges since only the proxy must access the socket as root and nothing else
7269
if err := syscall.Setgid(proxyGID); err != nil {
73-
log.Fatalf("could not set GID to %d %v", proxyGID, err)
70+
Eleven.LogFatal("could not set GID to %d %v", proxyGID, err)
7471
}
7572

7673
if err := syscall.Setuid(proxyUID); err != nil {
77-
log.Fatalf("could not set UID to %d %v", proxyUID, err)
74+
Eleven.LogFatal("could not set UID to %d %v", proxyUID, err)
7875
}
7976
}
8077

@@ -104,54 +101,62 @@ func httpProxy(w http.ResponseWriter, r *http.Request){
104101
if((method == "GET" || method == "HEAD") && !httpProxyBlockedPaths(url)){
105102
proxy.ServeHTTP(w, r)
106103
}else{
107-
log.Printf("blocked: %s %s", method, url)
104+
Eleven.Log("INF", "blocked: %s %s", method, url)
108105
http.Error(w, "", http.StatusForbidden)
109106
}
110107
}
111108

109+
func healthcheck(exit bool){
110+
healthcheckSockerDialer := &net.Dialer{Timeout: 2*time.Second}
111+
socket, err := healthcheckSockerDialer.Dial("unix", socketProxy)
112+
if err != nil {
113+
os.Exit(1)
114+
}
115+
err = socket.Close()
116+
if err != nil {
117+
os.Exit(1)
118+
}
119+
if(exit){
120+
os.Exit(0)
121+
}else{
122+
Eleven.Log("DBG", "health check successfully")
123+
}
124+
}
125+
112126
func main(){
113127
// set socket proxy file path
114-
socketProxy = regexp.MustCompile(`/+$`).ReplaceAllString(os.Getenv("SOCKET_PROXY_VOLUME"), "") + "/docker.sock"
115-
116-
// check for command line flags
117-
healthCheckFlag := flag.Bool("healthcheck", false, "just run healthcheck")
118-
flag.Parse()
128+
socketProxy = regexp.MustCompile(`/+$`).ReplaceAllString(volume, "") + "/docker.sock"
119129

120-
if(*healthCheckFlag){
130+
if(Eleven.Util.CommandLineArgumentExists("--healthcheck")){
121131
// only run healthcheck
122-
_, err := net.Dial("unix", socketProxy)
123-
if err != nil {
124-
os.Exit(1)
125-
}
126-
os.Exit(0)
132+
healthcheck(true)
127133
}else{
128-
log.Println("starting socket-proxy v" + os.Getenv("APP_VERSION"))
134+
// start app
135+
Eleven.Log("START", "")
136+
129137
// setup signal handler
130-
signals()
138+
signalChannel := make(chan os.Signal, 1)
139+
signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT)
140+
go func(){
141+
<-signalChannel
142+
os.Exit(1)
143+
}()
131144

132145
// setup proxy to docker socket as root
133-
keepAlive, err := time.ParseDuration(os.Getenv("SOCKET_PROXY_KEEPALIVE"))
146+
keepAlive, err := time.ParseDuration(keepAlive)
134147
if err != nil {
135-
log.Fatalf("%s not a valid time format: %s", os.Getenv("SOCKET_PROXY_KEEPALIVE"), err)
148+
Eleven.LogFatal("%s not a valid time format: %s", keepAlive, err)
136149
}
137-
timeout, err := time.ParseDuration(os.Getenv("SOCKET_PROXY_TIMEOUT"))
150+
timeout, err := time.ParseDuration(timeout)
138151
if err != nil {
139-
log.Fatalf("%s not a valid time format: %s", os.Getenv("SOCKET_PROXY_TIMEOUT"), err)
140-
}
141-
docketSockerDialer := &net.Dialer{KeepAlive: keepAlive, Timeout: timeout}
142-
dockerSocket, err := docketSockerDialer.Dial("unix", os.Getenv("SOCKET_PROXY_DOCKER_SOCKET"))
143-
if err != nil {
144-
log.Fatalf("could not access docker socket %v", err)
152+
Eleven.LogFatal("%s not a valid time format: %s", timeout, err)
145153
}
146154
localhost, _ := url.Parse("http://localhost")
147155
proxy = httputil.NewSingleHostReverseProxy(localhost)
156+
docketSockerDialer := &net.Dialer{KeepAlive: keepAlive, Timeout: timeout}
148157
proxy.Transport = &http.Transport{
149-
DialContext: func(_ context.Context, _, _ string)(net.Conn, error){
150-
dockerSocket, err = docketSockerDialer.Dial("unix", os.Getenv("SOCKET_PROXY_DOCKER_SOCKET"))
151-
if err != nil {
152-
log.Fatalf("could not access docker socket %v", err)
153-
}
154-
return dockerSocket, err
158+
DialContext:func(_ context.Context, _, _ string)(net.Conn, error){
159+
return(docketSockerDialer.Dial("unix", dockerSocket))
155160
},
156161
}
157162

@@ -165,14 +170,14 @@ func main(){
165170
os.Remove(socketProxy)
166171
unix, err := net.Listen("unix", socketProxy)
167172
if err != nil {
168-
log.Fatalf("could not start unix socket %v", err)
173+
Eleven.LogFatal("could not start unix socket %v", err)
169174
}
170175
wg.Add(1)
171176
go func(){
172177
defer wg.Done()
173-
log.Println("starting proxy UNIX socket ...")
178+
Eleven.Log("INF", "starting proxy UNIX socket ...")
174179
if err := unixServer.Serve(unix); err != nil {
175-
log.Fatalf("could not start unix socket %v", err)
180+
Eleven.LogFatal("could not start unix socket %v", err)
176181
}
177182
}()
178183

@@ -183,33 +188,43 @@ func main(){
183188

184189
tcp, err := net.Listen("tcp", "0.0.0.0:2375")
185190
if err != nil {
186-
log.Fatalf("could not start tcp socket %v", err)
191+
Eleven.LogFatal("could not start tcp socket %v", err)
187192
}
188193
wg.Add(1)
189194
go func(){
190195
defer wg.Done()
191-
log.Println("starting proxy TCP socket ...")
196+
Eleven.Log("INF", "starting proxy TCP socket ...")
192197
if err := httpServer.Serve(tcp); err != nil {
193-
log.Fatalf("could not start tcp socket %v", err)
198+
Eleven.LogFatal("could not start tcp socket %v", err)
194199
}
195200
}()
196201

197202
// try to access the socket proxy
198203
client := &http.Client{}
199204
req, err := http.NewRequest(http.MethodGet, "http://localhost:2375/version", nil)
200205
if err != nil {
201-
log.Fatalf("could not create HTTP request %v", err)
206+
Eleven.LogFatal("could not create HTTP request %v", err)
202207
}
203208
res, err := client.Do(req)
204209
if err != nil {
205-
log.Fatalf("could not proxy to docker socket %v", err)
210+
Eleven.LogFatal("could not proxy to docker socket %v", err)
206211
}
207212
res.Body.Close()
208213
if res.StatusCode != http.StatusOK {
209-
log.Fatalf("could not proxy to docker socket %v", err)
214+
Eleven.LogFatal("could not proxy to docker socket %v", err)
215+
}
216+
217+
// set internal socket check
218+
ticker := time.NewTicker(5 * time.Second)
219+
defer ticker.Stop()
220+
for {
221+
select {
222+
case <-ticker.C:
223+
healthcheck(false)
224+
}
210225
}
211-
log.Println("proxy connection to docker socket established")
212226

227+
// wait for socket to get stopped
213228
wg.Wait()
214229
}
215230
}

0 commit comments

Comments
 (0)