Documentation

Hexagonal architecture

This pattern is also known as Ports and Adapters, or Onion architecture. While the latter would be the most accurate (the separation between the layers is what matters, not the 6 sides), it's usually drawn with hexagons and so the name stuck.

The layers and elements of the hexagonal architecture.

The purpose of the hexagonal architecture in contrast with, say, a simple layered architecture, is to separate the domain logic from the application logic.
As you do not want to be coupling things like HTTP requests, database queries and domain model modifications together, you'll need a way to divide them.

To achieve this separation, an object is only allowed to interact with objects in the same layer or deeper. It's never allowed to interact with layers further to the outside.
You'll put most of the domain logic inside the domain model, while the domain services are responsible for the bits of logic that span multiple aggregates. The controllers manage you HTTP requests and the repositories [1]Sometimes people put repository interfaces inside the domain service layer (though never the implementations).

In my opinion this is cheating, as there's no point in pretending that interacting with an interface will really not perform any actual object storage logic.
your queries of course. That leaves the application services to tie everything together.
If you have logic that spans multiple bounded contexts, you'll usually want the communication to go via events and that's where you'll need event handlers. They function a bit like a controllers, but react to events instead of HTTP requests.