Pre-built image works locally, but on fly: `sh: line 1: gunicorn: command not found`

I have an image which I am building with Nix, which runs ok on my machine
The nix expression:

packages.docker = pkgs.dockerTools.streamLayeredImage {
	name = "nickel_club";
	contents = [ 

		# TODO remove debugging deps
	config = {
		Cmd = [ "sh" "-c" "gunicorn --bind\${PORT} 'nickel_club:create_app()'"]; 

Running it works:

⮞ docker run -itp 8080:8080 --env-file .env
[2022-09-13 06:47:51 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2022-09-13 06:47:51 +0000] [1] [INFO] Listening at: (1)
< ... snip >

I push to the fly registry successfully

⮞ docker push
< ... snip >
latest: digest: sha256:7e3757875902c9b032697de3d489ce4b2f8a70db0a973cc8b07a0d1f44a37014 size: 12276

Now I do a deploy with this fly.toml

# fly.toml file generated for nickel-club on 2022-09-11T13:06:12+10:00

app = "nickel-club"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

  image = ""


  allowed_public_ports = []
  auto_rollback = true

  http_checks = []
  internal_port = 8080
  processes = ["app"]
  protocol = "tcp"
  script_checks = []
    hard_limit = 25
    soft_limit = 20
    type = "connections"

    force_https = true
    handlers = ["http"]
    port = 80

    handlers = ["tls", "http"]
    port = 443

    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

and get an error sh: line 1: gunicorn: command not found:

⮞ flyctl deploy
Update available 0.0.372 -> v0.0.390.
Run "flyctl version update" to upgrade.
==> Verifying app config
--> Verified app config
==> Building image
Searching for image '' remotely...
image found: img_ox20prj99d8vj1zq
==> Creating release
--> release v4 created

--> You can detach the terminal anytime without stopping the deployment
==> Monitoring deployment

 1 desired, 1 placed, 0 healthy, 1 unhealthy [restarts: 2]
Failed Instances

Failure #1

e561253a	       	4      	syd   	stop   	failed	             	2       	1m7s   	

Recent Events
TIMESTAMP           	TYPE           	MESSAGE
2022-09-13T06:56:57Z	Received       	Task received by client
2022-09-13T06:56:57Z	Task Setup     	Building Task Directory
2022-09-13T06:57:05Z	Started        	Task started by client
2022-09-13T06:57:07Z	Terminated     	Exit Code: 127
2022-09-13T06:57:07Z	Restarting     	Task restarting in 1.038070838s
2022-09-13T06:57:14Z	Started        	Task started by client
2022-09-13T06:57:16Z	Terminated     	Exit Code: 127
2022-09-13T06:57:16Z	Restarting     	Task restarting in 1.057473798s
2022-09-13T06:57:23Z	Started        	Task started by client
2022-09-13T06:57:25Z	Terminated     	Exit Code: 127
2022-09-13T06:57:25Z	Not Restarting 	Exceeded allowed attempts 2 in interval 5m0s and mode is "fail"
2022-09-13T06:57:25Z	Alloc Unhealthy	Unhealthy because of failed task
2022-09-13T06:57:26Z	Killing        	Sent interrupt. Waiting 5s before force killing

2022-09-13T06:57:05Z   [info]Configuring firecracker
2022-09-13T06:57:05Z   [info]Starting virtual machine
2022-09-13T06:57:05Z   [info]Starting init (commit: 249766e)...
2022-09-13T06:57:05Z   [info]Preparing to run: `sh -c gunicorn --bind${PORT} 'nickel_club:create_app()'` as root
2022-09-13T06:57:05Z   [info]2022/09/13 06:57:05 listening on [fdaa:0:9d04:a7b:8566:e561:253a:2]:22 (DNS: [fdaa::3]:53)
2022-09-13T06:57:06Z   [info]Starting clean up.
2022-09-13T06:57:12Z   [info]Starting instance
2022-09-13T06:57:13Z   [info]Configuring virtual machine
2022-09-13T06:57:13Z   [info]Pulling container image
2022-09-13T06:57:14Z   [info]Unpacking image
2022-09-13T06:57:14Z   [info]Preparing kernel init
2022-09-13T06:57:14Z   [info]Configuring firecracker
2022-09-13T06:57:14Z   [info]Starting virtual machine
2022-09-13T06:57:14Z   [info]Starting init (commit: 249766e)...
2022-09-13T06:57:14Z   [info]Preparing to run: `sh -c gunicorn --bind${PORT} 'nickel_club:create_app()'` as root
2022-09-13T06:57:14Z   [info]2022/09/13 06:57:14 listening on [fdaa:0:9d04:a7b:8566:e561:253a:2]:22 (DNS: [fdaa::3]:53)
2022-09-13T06:57:14Z   [info]sh: line 1: gunicorn: command not found
2022-09-13T06:57:15Z   [info]Starting clean up.
2022-09-13T06:57:21Z   [info]Starting instance
2022-09-13T06:57:22Z   [info]Configuring virtual machine
2022-09-13T06:57:22Z   [info]Pulling container image
2022-09-13T06:57:23Z   [info]Unpacking image
2022-09-13T06:57:23Z   [info]Preparing kernel init
2022-09-13T06:57:23Z   [info]Configuring firecracker
2022-09-13T06:57:23Z   [info]Starting virtual machine
2022-09-13T06:57:23Z   [info]Starting init (commit: 249766e)...
2022-09-13T06:57:23Z   [info]Preparing to run: `sh -c gunicorn --bind${PORT} 'nickel_club:create_app()'` as root
2022-09-13T06:57:23Z   [info]2022/09/13 06:57:23 listening on [fdaa:0:9d04:a7b:8566:e561:253a:2]:22 (DNS: [fdaa::3]:53)
2022-09-13T06:57:23Z   [info]sh: line 1: gunicorn: command not found
2022-09-13T06:57:24Z   [info]Starting clean up.
--> v4 failed - Failed due to unhealthy allocations - rolling back to job version 3 and deploying as v5

--> Troubleshooting guide at
Error abort

What am I doing wrong? Why is there a difference in behaviour between my local machine and the deploy environment?

Please let me know if there are any other details I should post.