The common containers in Java EE are servlet container and the EJB container, and I see these as examples of IoC(Inversion of Control) containers. The crucial aspects are :
Your code does not have any main() or “wait here for a request logic” – the container starts up and configures itself and then eventually initialises your code and delivers requests
Your code may be one of many similar classes (servlets in a servlet container, EJBs in an EJB container) whose instances have life-cycles to be controlled by the container.
Requests are delivered to your servlet or EJB via some protocol defined by the container, using resources (eg. HTTP ports) controlled by the container, and possibly with considerable infrastructure cleverness (look at the HTTP request queues, EJB load balancing etc.)
There’s considerable added value from functions such as transaction control and security management – as the container is calling your code it is well-placed to implement this unintrusively.
The main container functionality is very much IOC, the container calls your code at appropriate times, however the container will also provide useful APIs that your code can call (eg. to get Servlet or EJB Contexts.
Referring more generally to the Container pattern (of which an enterprise Java container could be considered a specialization), the book Server Component Patterns by M.Volter, et al. offers the following:
[A CONTAINER provides] an execution environment that is responsible
for adding the technical concerns to the COMPONENTS…Conceptually, it
wraps the COMPONENTS, thus giving clients the illusion of of
tightly-integrated functional and technical concerns.
Examples of such technical concerns include security, transaction management, logging, etc.