How do I make NFS volumes reliable in Docker?
There are options in docker that will retry the startup of a container, restart in version 2 and restart-policy in version 3 (you'd need compatibility mode enabled for the version 3 syntax to work). However, I believe they only work when the issue is from the application inside the container fails, not when there is an issue creating the container like you see with a volume mount failing (or would also happen if the image couldn't be retrieved from a registry).

To handle the failing volume mount, I believe swarm mode is your best option despite your objections. You can create a single node cluster with docker swarm init and deploy your compose file with docker stack deploy -c docker-compose.yml stack_name, making an easy transition from docker-compose. Swarm mode looks at the overall state of the service and continuously tries to make the current state match your target state (as defined in the compose file), which will handle a failing volume mount that eventually corrects itself. I don't have an NFS server to test on right now, but here's a scenario with a bind mount to a missing folder:

$ cat docker-compose.vol-bind.yml
version: '3'
volumes:
  bind-test:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /home/bmitch/data/docker/test/missing
services:
  bind-test:
    image: busybox
    command: tail -f /dev/null
    volumes:
      - bind-test:/bind-test

$ docker stack deploy -c docker-compose.vol-bind.yml voltest   
Creating network voltest_default                              
Creating service voltest_bind-test   

$ docker service ls
ID                  NAME                   MODE                REPLICAS            IMAGE                                             PORTS
omzaeo7mrour        voltest_bind-test      replicated          0/1                 busybox:latest

$ docker service ps omzaeo7mrour
ID                  NAME                      IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR                              POR
TS
kpz0l79eucaw        voltest_bind-test.1       busybox:latest      bmitch-asusr556l    Ready               Ready 2 seconds ago
j6fylzhvcv60         \_ voltest_bind-test.1   busybox:latest      bmitch-asusr556l    Shutdown            Failed 5 seconds ago    "starting container failed: er…"
61o6raohp0xl         \_ voltest_bind-test.1   busybox:latest      bmitch-asusr556l    Shutdown            Failed 12 seconds ago   "starting container failed: er…"

$ docker inspect kpz0l79eucaw
[
    {
        "ID": "kpz0l79eucaw1856obmwvcak1",
        "Version": {
            "Index": 445
        },
        "CreatedAt": "2019-04-29T12:57:25.925788528Z",
        "UpdatedAt": "2019-04-29T12:57:34.3467203Z",
        "Labels": {},
        "Spec": {
            "ContainerSpec": {
                "Image": "busybox:latest",
                "Labels": {
                    "com.docker.stack.namespace": "voltest"
                },
...
        "Status": {
            "Timestamp": "2019-04-29T12:57:33.936048295Z",
            "State": "failed",
            "Message": "starting",
            "Err": "starting container failed: error while mounting volume '/home/var-docker/volumes/voltest_bind-test/_data': failed to mount local volume: mount /home
/bmitch/data/docker/test/missing:/home/var-docker/volumes/voltest_bind-test/_data, flags: 0x1000: no such file or directory",
            "ContainerStatus": {
                "ContainerID": "4c75c851bd43b5ef57b4785a4611f78501279933822eab90c693e1108f53ee82",
                "PID": 0,
                "ExitCode": 128
            },
            "PortStatus": {}
        },
...

$ mkdir missing

$ docker service ps omzaeo7mrour
ID                  NAME                      IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR                              POR
TS
okylli7smu1c        voltest_bind-test.1       busybox:latest      bmitch-asusr556l    Running             Running 4 seconds ago
9tpm188ysu2k         \_ voltest_bind-test.1   busybox:latest      bmitch-asusr556l    Shutdown            Failed 14 seconds ago   "starting container failed: er…"
kpz0l79eucaw         \_ voltest_bind-test.1   busybox:latest      bmitch-asusr556l    Shutdown            Failed 21 seconds ago   "starting container failed: er…"


From the above, you can see as soon as the missing directory was created, the bind mount succeeded, and the container that failed to be created as retried and started successfully.