From cc0d0ef8d02af24b823212d6c814319634b35c15 Mon Sep 17 00:00:00 2001 From: Julien Portalier Date: Wed, 31 May 2023 17:49:41 +0200 Subject: [PATCH 1/3] Port to Crystal --- .gitignore | 3 +- Dockerfile | 26 ++-- shard.lock | 10 ++ shard.yml | 18 +++ src/docker.cr | 76 ++++++++++ src/docker/params.cr | 62 ++++++++ src/docker/schemas.cr | 340 ++++++++++++++++++++++++++++++++++++++++++ src/monitor.cr | 42 ++++++ 8 files changed, 562 insertions(+), 15 deletions(-) create mode 100644 shard.lock create mode 100644 shard.yml create mode 100644 src/docker.cr create mode 100644 src/docker/params.cr create mode 100644 src/docker/schemas.cr create mode 100644 src/monitor.cr diff --git a/.gitignore b/.gitignore index dd3516c..5cb9637 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -monitor +/bin +/lib diff --git a/Dockerfile b/Dockerfile index 722aca4..89fbf53 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,21 @@ -FROM golang:1.20-alpine AS build +# BUILD image +FROM crystallang/crystal:1.8-alpine AS build +COPY . /src +RUN cd /src && shards build --release --static -COPY go.mod go.sum monitor.go /go/src/ -RUN cd /go/src && go build monitor.go +# RELEASE image +FROM jwilder/nginx-proxy:alpine AS release +RUN apk add --no-cache dnsmasq -FROM jwilder/nginx-proxy:latest AS release - -RUN apt-get -q update && \ - apt-get install -y -q --no-install-recommends dnsmasq && \ - apt-get -q clean && rm -r /var/lib/apt/lists/* - -# override nginx configs +# override nginx configs & nginx-proxy templating COPY *.conf /etc/nginx/conf.d/ - -# override nginx-proxy templating COPY nginx.tmpl Procfile /app/ -COPY --from=build /go/src/monitor /app/ -# COPY htdocs /var/www/default/htdocs/ +# install executable +COPY --from=build /src/bin/monitor /app/ +# default configuration ENV DOMAIN_TLD lvh.me +ENV NETWORK_NAME shared ENV DNS_IP 127.0.0.1 ENV HOSTMACHINE_IP 127.0.0.1 diff --git a/shard.lock b/shard.lock new file mode 100644 index 0000000..ccbe558 --- /dev/null +++ b/shard.lock @@ -0,0 +1,10 @@ +version: 2.0 +shards: + docker: + git: https://github.com/jeromegn/docker.cr.git + version: 0.2.0 + + json_mapping: + git: https://github.com/crystal-lang/json_mapping.cr.git + version: 0.1.1 + diff --git a/shard.yml b/shard.yml new file mode 100644 index 0000000..2b5c6d6 --- /dev/null +++ b/shard.yml @@ -0,0 +1,18 @@ +name: dockerdev +version: 0.1.0 + +authors: + - Julien Portalier + +description: | + DockerDev HTTP Proxy + +dependencies: + docker: + github: jeromegn/docker.cr + +targets: + monitor: + main: src/monitor.cr + +license: MIT diff --git a/src/docker.cr b/src/docker.cr new file mode 100644 index 0000000..336711a --- /dev/null +++ b/src/docker.cr @@ -0,0 +1,76 @@ +require "docker" +require "./docker/schemas" +require "./docker/params" + +module Docker + def self.events(*, since : String? = nil, _until : String? = nil, filters : String? = nil, & : EventMessage ->) : Nil + client = Client.new + + query = Params.build do |qs| + qs.add("since", since) unless since.nil? + qs.add("until", _until) unless _until.nil? + qs.add("filters", filters) unless filters.nil? + end + + client.get("/v1.41/events?#{query}") do |response| + case response.status_code + when 200 + while line = response.body_io.gets + yield EventMessage.from_json(line) + end + when 400, 500 + raise ErrorResponse.from_json(response.body_io) + else + unexpected_response(response) + end + end + end + + def self.network_inspect?(id : String, *, verbose : Bool? = nil, scope : String? = nil) : Network? + query = Params.build do |qs| + qs.add("verbose", verbose) unless verbose.nil? + qs.add("scope", scope) unless scope.nil? + end + response = client.get("/v1.41/networks/#{URI.encode_path_segment(id)}?#{query}") + case response.status_code + when 200 + Network.from_json(response.body) + when 404 + # not found + when 500 + raise ErrorResponse.from_json(response.body) + else + unexpected_response(response) + end + end + + def self.network_create(network_config : NetworkCreateRequest) : NetworkCreateResponse + headers = HTTP::Headers{"Content-Type" => "application/json"} + response = client.post("/v1.41/networks/create", headers: headers, body: network_config.to_json) + case response.status_code + when 201 + NetworkCreateResponse.from_json(response.body) + when 403, 404, 500 + raise ErrorResponse.from_json(response.body) + else + unexpected_response(response) + end + end + + def self.network_connect(id : String, container : NetworkConnectRequest) : Nil + headers = HTTP::Headers{"Content-Type" => "application/json"} + response = client.post("/v1.41/networks/#{URI.encode_path_segment(id)}/connect", headers: headers, body: container.to_json) + case response.status_code + when 200 + # ok + when 403, 404, 500 + raise ErrorResponse.from_json(response.body) + else + unexpected_response(response) + end + end + + protected def self.unexpected_response(response : HTTP::Client::Response) + raise "Unexpected HTTP response status #{response.status_code} (#{response.status})" + end +end diff --git a/src/docker/params.cr b/src/docker/params.cr new file mode 100644 index 0000000..f5af5c7 --- /dev/null +++ b/src/docker/params.cr @@ -0,0 +1,62 @@ +require "uri/params" + +module Docker + struct Params + def self.build(&) : String + URI::Params.build do |qs| + yield new(qs) + end + end + + def initialize(@qs : URI::Params::Builder) + end + + def add(name : String, value : Enumerable, collection_format : String? = nil) : Nil + if collection_format == "multi" + value.each { |item| @qs.add(name : String, encode(val, nil)) } + else + @qs.add(name : String, encode(val, collection_format)) + end + end + + def add(name : String, value, collection_format : String? = nil) : Nil + @qs.add(name, encode(value, nil)) + end + + def encode(value : Enumerable, collection_format : String?) : String + String.build do |str| + value.each_with_index do |item, i| + unless i == 0 + case collection_format + when "ssv" + str << ' ' + when "tsv" + str << '\t' + when "pipes" + str << '|' + else + str << ',' # csv + end + end + str << encode(item) + end + end + end + + def encode(value : Bool, collection_format : String? = nil) : String + value ? "1" : "0" + end + + def encode(value : String, collection_format : String? = nil) : String + value + end + + def encode(value : Time, collection_format : String? = nil) : String + value.to_rfc3339 + end + + def encode(value, collection_format : String? = nil) : String + param.to_s + end + end +end diff --git a/src/docker/schemas.cr b/src/docker/schemas.cr new file mode 100644 index 0000000..4030687 --- /dev/null +++ b/src/docker/schemas.cr @@ -0,0 +1,340 @@ +module Docker + class ErrorResponse < Exception + def self.new(pull : JSON::PullParser) + message = nil + pull.read_object do |key| + if key == "message" + message = pull.read_string + end + end + new message.not_nil! + end + end + + class EventMessage + include JSON::Serializable + + @[JSON::Field(key: "Type")] + property! type : String? + + @[JSON::Field(key: "Action")] + property! action : String? + + @[JSON::Field(key: "Actor")] + property! actor : EventActor? + + @[JSON::Field(key: "scope")] + property! scope : String? + + @[JSON::Field(key: "time")] + property! time : Int64 + + @[JSON::Field(key: "timeNano")] + property! time_nano : Int64? + + def initialize( + @type : String? = nil, + @action : String? = nil, + @actor : EventActor? = nil, + @scope : String? = nil, + @time : Int64? = nil, + @time_nano : Int64? = nil) + end + end + + class EventActor + include JSON::Serializable + + @[JSON::Field(key: "ID")] + property! id : String? + + @[JSON::Field(key: "Attributes")] + property! attributes : Hash(String, String)? + + def initialize( + @id : String? = nil, + @attributes : Hash(String, String)? = nil) + end + end + + class IPAM + include JSON::Serializable + + @[JSON::Field(key: "Driver")] + property! driver : String? + + @[JSON::Field(key: "Config")] + property! config : Array(IPAMConfig)? + + @[JSON::Field(key: "Options")] + property! options : Hash(String, String)? + + def initialize( + @driver : String? = nil, + @config : Array(IPAMConfig)? = nil, + @options : Hash(String, String)? = nil) + end + end + + class IPAMConfig + include JSON::Serializable + + @[JSON::Field(key: "Subnet")] + property! subnet : String? + + @[JSON::Field(key: "IPRange")] + property! ip_range : String? + + @[JSON::Field(key: "Gateway")] + property! gateway : String? + + @[JSON::Field(key: "AuxiliaryAddresses")] + property! auxiliary_addresses : Hash(String, String)? + + def initialize( + @subnet : String? = nil, + @ip_range : String? = nil, + @gateway : String? = nil, + @auxiliary_addresses : Hash(String, String)? = nil) + end + end + + class Network + include JSON::Serializable + + @[JSON::Field(key: "Name")] + property! name : String? + + @[JSON::Field(key: "Id")] + property! id : String? + + @[JSON::Field(key: "Created")] + property! created : Time? + + @[JSON::Field(key: "Scope")] + property! scope : String? + + @[JSON::Field(key: "Driver")] + property! driver : String? + + @[JSON::Field(key: "EnableIPv6")] + property! enable_ipv6 : Bool? + + @[JSON::Field(key: "IPAM")] + property! ipam : IPAM? + + @[JSON::Field(key: "Internal")] + property! internal : Bool? + + @[JSON::Field(key: "Attachable")] + property! attachable : Bool? + + @[JSON::Field(key: "Ingress")] + property! ingress : Bool? + + @[JSON::Field(key: "Containers")] + property! containers : Hash(String, NetworkContainer)? + + @[JSON::Field(key: "Options")] + property! options : Hash(String, String)? + + @[JSON::Field(key: "Labels")] + property! labels : Hash(String, String)? + + def initialize( + @name : String? = nil, + @id : String? = nil, + @created : Time? = nil, + @scope : String? = nil, + @driver : String? = nil, + @enable_ipv6 : Bool? = nil, + @ipam : IPAM? = nil, + @internal : Bool? = nil, + @attachable : Bool? = nil, + @ingress : Bool? = nil, + @containers : Hash(String, NetworkContainer)? = nil, + @options : Hash(String, String)? = nil, + @labels : Hash(String, String) = nil) + end + end + + class NetworkContainer + include JSON::Serializable + + @[JSON::Field(key: "Name")] + property! name : String? + + @[JSON::Field(key: "EndpointID")] + property! endpoint_id : String? + + @[JSON::Field(key: "MacAddress")] + property! mac_address : String? + + @[JSON::Field(key: "IPv4Address")] + property! ipv4_address : String? + + @[JSON::Field(key: "IPv6Address")] + property! ipv6_address : String? + + def initialize( + @name : String? = nil, + @endpoint_id : String? = nil, + @mac_address : String? = nil, + @ipv4_address : String? = nil, + @ipv6_address : String? = nil) + end + end + + class NetworkConnectRequest + include JSON::Serializable + + @[JSON::Field(key: "Container")] + property! container : String? + + @[JSON::Field(key: "EndpointConfig")] + property! endpoint_config : EndpointSettings? + + def initialize( + @container : String? = nil, + @endpoint_config : EndpointSettings? = nil) + end + end + + class NetworkCreateRequest + include JSON::Serializable + + @[JSON::Field(key: "Name")] + property name : String + + @[JSON::Field(key: "CheckDuplicate")] + property! check_duplicate : Bool? + + @[JSON::Field(key: "Driver")] + property! driver : String? + + @[JSON::Field(key: "Internal")] + property! internal : Bool? + + @[JSON::Field(key: "Attachable")] + property! attachable : Bool? + + @[JSON::Field(key: "Ingress")] + property! ingress : Bool? + + @[JSON::Field(key: "IPAM")] + property! ipam : IPAM? + + @[JSON::Field(key: "EnableIPv6")] + property! enable_ipv6 : Bool? + + @[JSON::Field(key: "Options")] + property! options : Hash(String, String)? + + @[JSON::Field(key: "Labels")] + property! labels : Hash(String, String)? + + def initialize( + @name : String, + @check_duplicate : Bool? = nil, + @driver : String? = nil, + @internal : Bool? = nil, + @attachable : Bool? = nil, + @ingress : Bool? = nil, + @ipam : ::Docker::IPAM? = nil, + @enable_ipv6 : Bool? = nil, + @options : Hash(String, String)? = nil, + @labels : Hash(String, String)? = nil) + end + end + + class NetworkCreateResponse + include JSON::Serializable + + @[JSON::Field(key: "Id")] + property! id : String? + + @[JSON::Field(key: "Warning")] + property! warning : String? + + def initialize(@id : String? = nil, @warning : String? = nil) + end + end + + class EndpointSettings + include JSON::Serializable + + @[JSON::Field(key: "IPAMConfig")] + property! ipam_config : EndpointIPAMConfig? + + @[JSON::Field(key: "Links")] + property! links : Array(String)? + + @[JSON::Field(key: "Aliases")] + property! aliases : Array(String)? + + @[JSON::Field(key: "NetworkID")] + property! network_id : String? + + @[JSON::Field(key: "EndpointID")] + property! endpoint_id : String? + + @[JSON::Field(key: "Gateway")] + property! gateway : String? + + @[JSON::Field(key: "IPAddress")] + property! ip_address : String? + + @[JSON::Field(key: "IPPrefixLen")] + property! ip_prefix_len : Int64? + + @[JSON::Field(key: "IPv6Gateway")] + property! ipv6_gateway : String? + + @[JSON::Field(key: "GlobalIPv6Address")] + property! global_ipv6_address : String? + + @[JSON::Field(key: "GlobalIPv6PrefixLen")] + property! global_ipv6_prefix_len : Int64? + + @[JSON::Field(key: "MacAddress")] + property! mac_address : String? + + @[JSON::Field(key: "DriverOpts")] + property! driver_opts : Hash(String, String)? + + def initialize( + @ipam_config : EndpointIPAMConfig? = nil, + @links : Array(String)? = nil, + @aliases : Array(String)? = nil, + @network_id : String? = nil, + @endpoint_id : String? = nil, + @gateway : String? = nil, + @ip_address : String? = nil, + @ip_prefix_len : Int64? = nil, + @ipv6_gateway : String? = nil, + @global_ipv6_address : String? = nil, + @global_ipv6_prefix_len : Int64? = nil, + @mac_address : String? = nil, + @driver_opts : Hash(String, String)? = nil) + end + end + + class EndpointIPAMConfig + include JSON::Serializable + + @[JSON::Field(key: "IPv4Address")] + property! ipv4_address : String? + + @[JSON::Field(key: "IPv6Address")] + property! ipv6_address : String? + + @[JSON::Field(key: "LinkLocalIPs")] + property! link_local_ips : Array(String)? + + def initialize( + @ipv4_address : String? = nil, + @ipv6_address : String? = nil, + @link_local_ips : Array(String)? = nil) + end + end +end diff --git a/src/monitor.cr b/src/monitor.cr new file mode 100644 index 0000000..5da534e --- /dev/null +++ b/src/monitor.cr @@ -0,0 +1,42 @@ +require "log" +require "./docker" + +DOMAIN = ENV.fetch("DOMAIN_TLD", "lvh.me") +NETWORK_NAME = ENV.fetch("NETWORK_NAME", "shared") + +Log.setup_from_env + +if network = Docker.network_inspect?(NETWORK_NAME) + Log.info { "Using existing network name=#{network.name} id=#{network.id[0, 12]}" } +else + network = Docker.network_create(Docker::NetworkCreateRequest.new(name: NETWORK_NAME)) + Log.info { "Created network name=#{NETWORK_NAME} id=#{network.id[0, 12]}" } +end + +Log.info { "Waiting for container:create events" } + +filters = { + type: {"container"}, + event: {"create"}, +} +Docker.events(filters: filters.to_json) do |event| + container_name = event.actor.attributes["name"] + Log.debug { "New container (#{container_name}) created" } + + next unless project = event.actor.attributes["com.docker.compose.project"]? + next unless service = event.actor.attributes["com.docker.compose.service"]? + oneoff = event.actor.attributes["com.docker.compose.oneoff"]? + network_config = Docker::NetworkConnectRequest.new(container: event.actor.id) + + if oneoff == "False" + dns_alias = {service, project, DOMAIN}.join('.') + network_config.endpoint_config = Docker::EndpointSettings.new(aliases: [dns_alias]) + Log.info { "Attaching #{container_name} to the #{NETWORK_NAME} network with alias #{dns_alias}" } + else + Log.info { "Attaching #{event.actor.id} to the #{NETWORK_NAME} network" } + end + + Docker.network_connect(network.id, network_config) +rescue ex : Docker::ErrorResponse + Log.error(exception: ex) { ex.message } +end From caeadf8aa4baaaffe40a1aee184c2d08036c26f3 Mon Sep 17 00:00:00 2001 From: Julien Portalier Date: Wed, 31 May 2023 17:49:57 +0200 Subject: [PATCH 2/3] Remove Go version --- go.mod | 28 ----------- go.sum | 142 ----------------------------------------------------- monitor.go | 59 ---------------------- 3 files changed, 229 deletions(-) delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 monitor.go diff --git a/go.mod b/go.mod deleted file mode 100644 index cdd4106..0000000 --- a/go.mod +++ /dev/null @@ -1,28 +0,0 @@ -module manas.tech/dockerdev - -go 1.20 - -require github.com/fsouza/go-dockerclient v1.9.4 - -require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/containerd/containerd v1.6.14 // indirect - github.com/docker/docker v23.0.0+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/klauspost/compress v1.11.13 // indirect - github.com/moby/patternmatcher v0.5.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect - github.com/opencontainers/runc v1.1.2 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect - golang.org/x/tools v0.1.12 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 31789d7..0000000 --- a/go.sum +++ /dev/null @@ -1,142 +0,0 @@ -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.6.14 h1:W+d0AJKVG3ioTZZyQwcw1Y3vvo6ZDYzAcjDcY4tkgGI= -github.com/containerd/containerd v1.6.14/go.mod h1:U2NnBPIhzJDm59xF7xB2MMHnKtggpZ+phKg8o2TKj2c= -github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= -github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/docker v23.0.0+incompatible h1:L6c28tNyqZ4/ub9AZC9d5QUuunoHHfEH4/Ue+h/E5nE= -github.com/docker/docker v23.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v23.0.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= -github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsouza/go-dockerclient v1.0.0 h1:Ka6dzvCHe+oWdJIY0eoTXaXa77FmZNiJUpTeoFLvrcA= -github.com/fsouza/go-dockerclient v1.0.0/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0= -github.com/fsouza/go-dockerclient v1.9.4 h1:V7KGGCIoaQTRCQqhIMH1lvL1scnOWeZZq3jvQ0rLhUw= -github.com/fsouza/go-dockerclient v1.9.4/go.mod h1:w8kPIZLpXeohzR5os7o4VWllLL5oitqYE8T3zX8RCJg= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= -github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= -github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= -github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw= -github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg= -github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= diff --git a/monitor.go b/monitor.go deleted file mode 100644 index 9dd5a3d..0000000 --- a/monitor.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "log" - "os" - - docker "github.com/fsouza/go-dockerclient" -) - -func main() { - cli, err := docker.NewClientFromEnv() - if err != nil { - log.Fatal(err) - } - - listener := make(chan *docker.APIEvents, 10) - filters := map[string][]string{ - "type": {"container"}, - "event": {"create"}, - } - opts := docker.EventsOptions{Filters: filters} - err = cli.AddEventListenerWithOptions(opts, listener) - if err != nil { - log.Fatal(err) - } - - domain := os.Getenv("DOMAIN_TLD") - - log.Println("Listening events") - for { - event := <-listener - - containerName := event.Actor.Attributes["name"] - log.Printf("New container (%s) created\n", containerName) - - project, hasProject := event.Actor.Attributes["com.docker.compose.project"] - service, hasService := event.Actor.Attributes["com.docker.compose.service"] - oneoff := event.Actor.Attributes["com.docker.compose.oneoff"] - - if hasProject && hasService { - config := docker.NetworkConnectionOptions{Container: event.Actor.ID} - - if oneoff == "False" { - alias := service + "." + project + "." + domain - log.Printf("Attaching %s to the shared network with alias %s\n", containerName, alias) - config.EndpointConfig = &docker.EndpointConfig{ - Aliases: []string{alias}, - } - } else { - log.Printf("Attaching %s to the shared network\n", event.Actor.ID) - } - - err := cli.ConnectNetwork("shared", config) - if err != nil { - log.Fatal(err) - } - } - } -} From c2f9db42c222e63574a77e71fd3852120810945e Mon Sep 17 00:00:00 2001 From: Julien Portalier Date: Fri, 2 Jun 2023 12:23:24 +0200 Subject: [PATCH 3/3] Fix: use nginx-proxy:latest debian image instead of alpine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I got some issues with resolving domains across containers with the alpine image. Let's only port to crystal 😄 --- Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 89fbf53..a50bbb9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,11 @@ COPY . /src RUN cd /src && shards build --release --static # RELEASE image -FROM jwilder/nginx-proxy:alpine AS release -RUN apk add --no-cache dnsmasq +FROM jwilder/nginx-proxy:latest AS release + +RUN apt-get -q update && \ + apt-get install -y -q --no-install-recommends dnsmasq && \ + apt-get -q clean && rm -r /var/lib/apt/lists/* # override nginx configs & nginx-proxy templating COPY *.conf /etc/nginx/conf.d/