Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker volume - need permissions to write to database

I'm working on a flask server (in a virtualenv with python 3.5) which is used as a REST API (only for development as suggested for flask). In the beginning it connects to a local sqlite database and it will commit any db changes as soon as possible. Now I wanted to run everything in a docker container and I was wondering how I can access the database because the sqlite file is located in the container.

So I created a volume in a docker-compose file which points to the dockerfile building the application.

Dockerfile:

FROM python:latest
ENV HOME /home/parkrep
WORKDIR $HOME
ADD requirements.txt $HOME/requirements.txt
RUN pip install -r requirements.txt
ADD . $HOME
EXPOSE 80
CMD ["python", "server.py"]

.dockerignore

__pycache__
venv
.gitignore
.dockerignore
README.md
Dockerfile
docker-compose.yml

docker-compose.yml

version: '2'
services:
  parkrep:
    build:
      context: ./
      dockerfile: Dockerfile
    volumes:
      - ./output:/home/parkrep/output
    command: ["python", "server.py"]
    ports:
      - "80:80"

If I run docker-compose up I get the following

parkrep_1  |   File "/home/parkrep/db_connector.py", line 45, in _connect_db
parkrep_1  |     self._connection = sqlite3.connect(path, check_same_thread=False)
parkrep_1  | sqlite3.OperationalError: unable to open database file
parkrep_parkrep_1 exited with code 1

If I create the database at output/reports.db and start docker-compose again, it returns the following error:

parkrep_1  | sqlite3.OperationalError: attempt to write a readonly database

So obviously I don't have permissions to write to the file. I tested this behavior by writing to a test file which is mounted like this:

...
volumes:
  - ./output:/home/parkrep/output
  - ./test.txt:/home/parkrep/text.txt
command: bash -c "echo 'hallo' > test.txt"

Error message:

parkrep_1  | bash: text.txt: Permission denied

Let's see who owns this file:

parkrep_1  | drwxr-xr-x 7 root root 4.0K Dec 19 10:45 .
parkrep_1  | -rw-rw-r-- 1 root root  143 Dec 12 15:08 config.yaml
parkrep_1  | -rw-rw-r-- 1 root root 7.9K Dec 12 14:37 db_connector.py
parkrep_1  | drwxrwxr-x 2 4262 4262 4.0K Dec 19 11:10 output
parkrep_1  | -rw-rw-r-- 1 root root  144 Dec 12 13:20 requirements.txt
parkrep_1  | -rw-rw-r-- 1 root root 2.7K Dec 19 10:14 server.py
parkrep_1  | -rw-rw-r-- 1 4262 4262 2.7K Dec 19 10:14 test.txt

It turns out that there is no user 4262 in the container but on the host machine my user account has this id. So I think I know what the problem is now, but I have no clue how to get access to these files. I tried adding ":rw" to the volume definitions but I still don't have write permissions. How can I tell docker to not change the file/directory owner if a volume is defined.

I'm thinking of a problem with my local volume driver, but maybe someone else already had this problem and can tell me how to configure my image to get the required permissions.

Greetings, Thomas

docker info

     Containers: 1
 Running: 0
 Paused: 0
 Stopped: 1
Images: 19
Server Version: 1.12.5
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 19
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: host bridge null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-53-generic
Operating System: Ubuntu 16.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 15.56 GiB
Name: de3lxd-107769
ID: PU5F:LZ55:EEK7:W3R7:SYR3:336J:2VRH:35H2:MTLY:6Q6L:BWBP:EM5R
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Insecure Registries:
 127.0.0.0/8

docker-compose -v

docker-compose version 1.9.0, build 2585387

lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.1 LTS
Release:    16.04
Codename:   xenial
like image 874
Chaoste Avatar asked Dec 19 '16 11:12

Chaoste


People also ask

What is the best way to manage permissions for Docker shared volumes?

You can manage volumes using Docker CLI commands or the Docker API. Volumes work on both Linux and Windows containers. Volumes can be more safely shared among multiple containers. Volume drivers let you store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.

How do I fix Docker permission denied?

Similar to running a docker command without the sudo command, a stopped Docker Engine triggers the permission denied error. How do you fix the error? By restarting your Docker engine. Run the systemctl command below to confirm the Docker Engine's status ( status docker ) and if it's running.

Why should a containerized database use a Docker volume?

Container volumes Volumes provide the ability to connect specific filesystem paths of the container back to the host machine. If a directory in the container is mounted, changes in that directory are also seen on the host machine. If we mount that same directory across container restarts, we'd see the same files.

Can Docker container Access database on host?

You can also access the MySQL service running in your host machine in your Docker container using the bridge network mode. For that, you need to ensure that the MySQL service is actively listening for all the connections in the 172.17. 42.1 address.


1 Answers

Hot fix

I fixed the problem by giving writer permission to everyone.

mkdir output
touch output/reports.db output/database.log
chmod a+rw output output/*

This will give the user on the host machine and the root user in the docker machine permissions, no matter who owns the files. This is just a dirty fix, because I had to hurry up. Any process could access the and edit/delete the files. It would be better If only the docker user get's writing permission, but I couldn't give writer permission to the root user on the host machine.

Better approach

In this post they're using another user (www-data) in the container. After building the image they get the id of the user and replace the current file owner with this id. If you start the container as this user (www-data), the mount will copy the files with permissions and owner information, so the user can read and write to these files.

It would be a more secure way because you make sure that only the docker user can change the database/files. Because I couldn't make this work for me (seems to not work for root user with id=0), but I wanted to point out, that there is a better solution.

If you only need the data in the end after the docker stopped you might have a look at docker cp.

like image 55
Chaoste Avatar answered Oct 21 '22 15:10

Chaoste