A version 2 file could share a container’s volumes with volumes_from, which is how the data-container pattern worked. Version 3 removes it, because a scheduler placing containers on different hosts cannot honour it.
# v2
php:
volumes_from: [appdata]
# v3: name the volume and mount it in both
services:
php:
volumes: [appdata:/var/www]
nginx:
volumes: [appdata:/var/www:ro]
volumes:
appdata:
The named volume is better anyway — it has an identity, it survives docker-compose rm, and both services declare what they mount rather than one inheriting from the other. The migration is mechanical; the thing to check is that the read-only flag is still where it was, since volumes_from could carry it and the new form needs it stated per service.