Ad hoc file copying between host and Docker container
- Preparation
- Piping a file into a container
- Reading a file out of the container
- Reading the file within the container
- Update 2017-01-14
Docker supports file sharing between the host and a container via the -v
option, which allows a host directory to be accessible within the container at the specified mount point, For example, with docker run -v /path_on_the_host:/path_in_the_container postgres
, the host directory /path_on_the_host
can be accessed as /path_in_the_container
within the container. However, this requires the container being started already with the -v
option.
Can we copy files to and from a running container, which was started without -v
, without restarting it? Here is how to do that with piping.
Preparation
To test the solution, lets first start a postgres container from the official images:
$ docker run -p 5432:5432 --name postgres -e POSTGRES_PASSWORD=secret -d postgres
Assuming we want to execute some SQL queries against our postgres database in the container, and the queries are in a file, e.g.,
$ cat /tmp/version.sql
SELECT VERSION();
Piping a file into a container
$ cat /tmp/version.sql | docker exec -i -u 0 postgres /bin/bash -c 'cat > /tmp/version.sql'
Reading a file out of the container
$ docker exec -i -u 0 postgres /bin/bash -c 'cat /tmp/version.sql'
SELECT VERSION();
Reading the file within the container
$ docker exec -i -u 0 postgres bash -c 'psql -h localhost -f /tmp/version.sql -U postgres'
version
------------------------------------------------------------------------------------------
PostgreSQL 9.6.1 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
(1 row)
Just for completness, the above trivial example use case can also be fullfiled by directly piping the file content to psql, without using the temporary file, e.g.,
echo 'SELECT VERSION();' | docker exec -i -u 0 postgres bash -c 'psql -h localhost -U postgres'
Update 2017-01-14
It turns out that Docker has builtin support for file (and even folder) copying to and from a running container, using the docker cp
command, which is really cool!
Prepare test data
$ mkdir /tmp/test
$ echo 'Hello world!' > /tmp/test/test.txt
Copy from host to container
$ docker cp /tmp/test/ postgres:/tmp/
$ docker exec -i -u 0 postgres /bin/bash -c 'ls -l /tmp/test/'
total 4
-rw-rw-r--. 1 root root 13 Jan 14 14:56 test.txt
Copy from container to host
$ docker cp postgres:/tmp/test/test.txt /tmp/test.txt
$ cat /tmp/test.txt
Hello world!
Happy dockering!