-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Transition from bind mounts to named volumes #463
Comments
Hi @BuongiornoTexas - You are always tweaking!!! Thanks for always challenging the status quo with new insight and sharing your research. Would you be willing to share your I am familiar with named volumes and have used them. I have also been bitten by them with things like All that to say, I'm not comfortable making this change globally. In this case, the devil we know is manageable (self service support, easier issues, support discussions, etc). However, I'm happy to make this an option for the power users like yourself. We could also include something like |
TBH, supporting both power users and mainline users feels like a worst of both worlds option. I'd rather continue working with the mainstream package and managing issues myself rather than inflicting the pain of maintaining parallel trees on everyone else.
No problem on this - If you are interested in at least exploring the option a bit further, I'll go one better with a couple of days experimentation and providing a simple script for reversible migrations of both the grafana and telegraf containers (as these have the simplest setups). That said, if you are set on staying with bind, I'd rather just close this proposal out as a dead end.
I've had problems with pruning containers, but not volumes so far. (no data loss, but irritating), and it would be a thing to watch out for. However: a) using prune is very much a power user function - anyone who does it should be aware of possible consequences and b) the current version of docker does not remove volumes automatically, and we could add a keep filter to the docker config to give belt and braces protection (https://docs.docker.com/config/pruning/#prune-volumes). I'd still want to do a bit of testing to be sure, but on first look, I'd say protections are in place.
All of these are reasonable criticisms, but I also don't think these issues are as significant as you are suggesting. And I think the long term benefits of (mostly) separating container and host data space outweigh the problems (I guess I'm agreeing with dockers reasoning on this one). Touching on your points:
|
Thanks @BuongiornoTexas - I always appreciate your thoughtful responses. I'm happy leaving this open for others to review and comment as well. |
OK - I'll pull the demo scripts together and we can see if you and others like what you see. |
WARNING: the scripts below include use of So real life intervened and delayed things a bit, but here are the demo scripts/files. To run these, drop all three files in a directory parallel/at the same level as Powerwall-Dashboard (e.g.
test-named.sh
#!/bin/bash
# NOTE: Need to update powerwall.named.yml to match current repo powerwall.yml as far as possible before issue.
# script assumes we are in a folder parallel to Powerwall-Dashboard
WORKING="$(pwd)"
PWD="${WORKING}/../Powerwall-Dashboard"
# And broadly, we will work in the PWD for convenience.
cd "$PWD"
# belt and braces - create copy of powerwall.yml on FIRST RUN only.
cp -n powerwall.yml "${WORKING}/powerwall.bind.yml"
# Do preliminaries.
# If we wanted to create volumes manually, we could use commands similar to this.
# But I'm letting docker compose do this automatically.
# docker volume create pwd-grafana-rw
# docker volume create pwd-telegraf-ro
# Stop the bind containers.
docker stop grafana
docker stop telegraf
# Grab current uid/gid
PWD_OWNER="$(id -u $USER):$(id -g $USER)"
# Create a tar archive of the grafana configuration.
# Run as su to defang permissions problems. Note that we
# rewrite permissions on the fly to match the default grafana
# container uid and gid. And then we correct uid/gid of grafana file.
# (correcting uid/gid probably not be needed).
# This should only be neeed for transitioning from bind and has the
# added bonus that both normal and edges cases have the same handling.
echo "su password required to create tar archive of grafana config."
su -c "tar --owner=472 --group=0 -cvf ${WORKING}/grafana.tar grafana; chown $PWD_OWNER ${WORKING}/grafana.tar"
# Move grafana directory as part proof of concept
mv grafana grafana.bak
# update powerwall.yml
cp "${WORKING}/powerwall.named.yml" ./powerwall.yml
# create the containers, create the volumes as a byproduct.
# Will also prepopulate telegraf volume with sample files (we will overwrite)
bash compose-dash.sh create grafana-named
bash compose-dash.sh create telegraf-named
# Use busybox as a helper to unpack the tar archive, and yes, use a temporary bind for this.
# This is one of many ways to achieve this.
# (Could do this with docker cp and pipes as well).
# tar runs as root and preserves ownership and permissions from the tarfile.
docker run --rm --volumes-from grafana-named \
-v "${WORKING}:/backup" \
busybox sh -c "cd /var/lib/grafana && tar xvf /backup/grafana.tar --strip-components=1"
echo "List of volume /var/lib/grafana should have owners of 472:root"
docker run --rm --volumes-from grafana-named \
busybox sh -c "ls -l /var/lib/grafana"
# Use docker cp to update the telegraf config.
docker cp telegraf.conf telegraf-named:/etc/telegraf
docker cp telegraf.local telegraf-named:/etc/telegraf/telegraf.d/local.conf
# Bring the stack up.
bash compose-dash.sh up -d revert-named.sh
#!/bin/bash
# script assumes we are in a folder parallel to Powerwall-Dashboard
WORKING="$(pwd)"
PWD="${WORKING}/../Powerwall-Dashboard"
# And broadly, we will work in the PWD for convenience.
cd "$PWD"
# stopped named volume containers
docker stop grafana-named
docker stop telegraf-named
# reinstate grafana folder
mv grafana.bak grafana
# revert compose file to bind version
cp "${WORKING}/powerwall.bind.yml" ./powerwall.yml
echo " "
echo "Bring the stack back up."
echo " "
bash compose-dash.sh up -d
# Clean up named based containers and volumes
echo "Pruning stopped containers using named volumes to show it doesn't delete volumes."
echo "(command run once for each named container, hit y to OK each)"
echo "(However, given how brutal prune is, probably better to avoid this "
echo "altogether and use commands like remove orphans instead)."
echo " "
echo "WARNING: Before you run this command, probably worth using docker ps to check your stack is up."
echo "(The command should only delete the named containers, but just in case.)"
echo " "
docker container prune --filter "label=com.docker.compose.service=grafana-named"
docker container prune --filter "label=com.docker.compose.service=telegraf-named"
echo " "
echo "Data volumes for telegraf and grafana should still be present."
echo "Listing volumes now"
echo " "
docker volume list
echo " "
read -r -p "Removing test volumes. Hit y to proceed." response
echo " "
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
docker volume rm pwd-grafana-rw
docker volume rm pwd-telegraf-ro
fi powerwall.named.yml
volumes:
pwd-grafana-rw:
# external is only needed for managing volumes that will only
# be created externally. Probably not what we want.
# external: true
name: pwd-grafana-rw
pwd-telegraf-ro:
# Make it read only for the container in the service definition.
name: pwd-telegraf-ro
services:
influxdb:
image: influxdb:1.8
container_name: influxdb
hostname: influxdb
restart: unless-stopped
volumes:
- type: bind
source: ./influxdb.conf
target: /etc/influxdb/influxdb.conf
read_only: true
- type: bind
source: ./influxdb
target: /var/lib/influxdb
ports:
- "${INFLUXDB_PORTS:-8086:8086}"
env_file:
- influxdb.env
pypowerwall:
image: jasonacox/pypowerwall:0.8.2t53
container_name: pypowerwall
hostname: pypowerwall
restart: unless-stopped
volumes:
- type: bind
source: .auth
target: /app/.auth
user: "${PWD_USER:-1000:1000}"
ports:
- "${PYPOWERWALL_PORTS:-8675:8675}"
environment:
- PW_AUTH_PATH=.auth
env_file:
- pypowerwall.env
telegraf-named:
image: telegraf:1.28.2
container_name: telegraf-named
hostname: telegraf
restart: unless-stopped
# user is not required for named volume.
# as we can rely on the default user!
# woohoo no perms problems.
# user: "${PWD_USER:-1000:1000}"
command: [
"telegraf",
"--config",
"/etc/telegraf/telegraf.conf",
"--config-directory",
"/etc/telegraf/telegraf.d"
]
volumes:
- type: volume
source: pwd-telegraf-ro
target: /etc/telegraf
# we could make this read only.
# But is not needed as we keep master configs on host.
# read_only: true
depends_on:
- influxdb
- pypowerwall
grafana-named:
image: grafana/grafana:9.1.2-ubuntu
container_name: grafana-named
hostname: grafana
restart: unless-stopped
# user is not required for named volume.
# as we can rely on the default user!
# woohoo no perms problems.
# user: "${PWD_USER:-1000:1000}"
# Used named volume for grafana control data.
volumes:
- type: volume
source: pwd-grafana-rw
target: /var/lib/grafana
ports:
- "${GRAFANA_PORTS:-9000:9000}"
env_file:
- grafana.env
depends_on:
- influxdb
weather411:
image: jasonacox/weather411:0.2.3
container_name: weather411
hostname: weather411
restart: unless-stopped
user: "${PWD_USER:-1000:1000}"
volumes:
- type: bind
source: ./weather
target: /var/lib/weather
read_only: true
ports:
- "${WEATHER411_PORTS:-8676:8676}"
environment:
- WEATHERCONF=/var/lib/weather/weather411.conf
depends_on:
- influxdb |
Problem
PWD currently uses bind mounts for persistent storage on the host.
Docker recommends using volumes for persistent storage for a range of reasons (https://docs.docker.com/storage/volumes/). The main benefits for PWD would be:
I've done some brief experimentation and found that it is fairly straightforward to migrate the grafana binds to named volumes (took a couple of hours to put the pieces together, and is fairly small set of commands), and I'm pretty sure that it would be similar for the other bind mounts.
Enhancement
At least, transition read-write bind mounts to named volumes, as these appear to be the key pain points for permission issues. But if we do adopt this, it's probably worth transitioning all mounts for simplicity of future management.
Additional context
I'm happy to work up a test script to demonstrate the transition for grafana, and if this looks good, move on to PR(s) for the change. In addition to the transition, PRs would also need to address how to ensure conf files are updated within containers (
docker cp
) and detail a new backup procedure, as the volume data is managed in the docker data space.The text was updated successfully, but these errors were encountered: