{:error, :econnrefused} with ExAws.S3 and local Minio

Hi,

I’m setting up a dev environment for my current project using docker-compose. Everything works fine.

I added an S3 service using minio/minio image so I don’t hit the production S3 server while testing stuff. It seems to work too, as I can see the dashboard and upload files through it.

But I’m failing to make it work with ExAws. Whenever I try to upload a file like:

file_path
  |> ExAws.S3.Upload.stream_file()
  |> ExAws.S3.upload(bucket(), path, opts)
  |> ExAws.request()

It fails with {:error, :econnrefused}

ExAws is configured as:

config :ex_aws,
  debug_requests: true,
  region: "local"

config :ex_aws, :s3, %{
  access_key_id: "minioadmin",
  secret_access_key: "minioadmin",
  scheme: "http://",
  host: "localhost",
  port: 5000,
  region: "local",
  bucket: "uploads"
}

And it logs:

app_1     | [debug] Request URL: "http://localhost:5000/uploads/uploads/media/8de8a3a0-37d8-4da5-9a5b-c371223be9ff.gif?uploads=1"
app_1     | [debug] Request HEADERS: [{"Authorization", "AWS4-HMAC-SHA256 Credential=minioadmin/20200920/local/s3/aws4_request,SignedHeaders=content-length;content-type;host;x-amz-acl;x-amz-content-sha256;x-amz-date,Signature=93d180c17e16ca812fc0200e038ce9e4a13ec43fc8d995072a4ee28557b615fd"}, {"host", "localhost:5000"}, {"x-amz-date", "20200920T171910Z"}, {"content-length", 0}, {"content-type", "image/gif"}, {"x-amz-acl", "public-read"}, {"x-amz-content-sha256", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}]
app_1     | [debug] Request BODY: ""
app_1     | [warn] ExAws: HTTP ERROR: :econnrefused

IO.inspecting the request:

app_1     | %ExAws.S3.Upload{
app_1     |   bucket: "uploads",
app_1     |   opts: [acl: :public_read, content_type: "image/gif"],
app_1     |   path: "uploads/media/8de8a3a0-37d8-4da5-9a5b-c371223be9ff.gif",
app_1     |   service: :s3,
app_1     |   src: %File.Stream{
app_1     |     line_or_bytes: 5242880,
app_1     |     modes: [:raw, :read_ahead, :binary],
app_1     |     path: "/tmp/plug-1600/multipart-1600622348-348284052294283-2.gif",
app_1     |     raw: true
app_1     |   },
app_1     |   upload_id: nil
app_1     | }

and the docker-compose.yml service:

  s3:
    image: minio/minio
    ports:
      - "5000:9000"
    volumes:
      - "s3:/data"
    environment:
      MINIO_ACCESS_KEY: "minioadmin"
      MINIO_SECRET_KEY: "minioadmin"
    command: server /data

With the same code, it is running fine in production with DigitalOcean Spaces(no docker though), so I believe it has todo with the way things are configured here, but what can it be?

The issue was that I was configuring ExAws to use the port exposed by docker, but I needed to use the port in the docker network, which is 9000, not 5000, also the host should be the same name as the service, that is s3, not localhost

Good work! Thanks for sharing the solution!

I use the same setup except I use waffle and waffle_ecto to handle the uploads. It is quite easier to setup and use.