Yes, there are a couple of ways you can do this.
Docker Compose
In Docker Compose, you can supply environment variables in the file itself, or point to an external env file:
# docker-compose.yml
version: '2'
services:
service-name:
image: service-app
environment:
- GREETING=hello
env_file:
- .env
Incidentally, one nice feature that is somewhat related is that you can use multiple Compose files, with each subsequent one adding to the other. So if the above were to define a base, you can then do this (e.g. per run-time environment):
# docker-compose-dev.yml
version: '2'
services:
service-name:
environment:
- GREETING=goodbye
You can then run it thus:
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up
Docker only
To do this in Docker only, use your entrypoint or command to run an intermediate script, thus:
#Dockerfile
....
ENTRYPOINT ["sh", "bin/start.sh"]
And then in your start script:
#!/bin/sh
source .env
python /manager.py
I've used this related answer as a helpful reference for myself in the past.
Update on PID 1
To amplify my remark in the comments, if you make your entry point a shell or Python script, it is likely that Unix signals (stop, kill, etc) will not be passed onto your process. This is because that script will become process ID 1, which makes it the parent process of all other processes in the container - in Linux/Unix there is an expectation that this PID will forward signals to its children, but unless you explicitly implement that, it won't happen.
To rectify this, you can install an init system. I use dumb-init from Yelp. This repo also features plenty of detail if you want to understand it a bit better, or simple install instructions if you just want to "install and forget".