可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm thinking of using Docker to build my dependencies on a continuous integration (CI) server, so that I don't have to install all the runtimes and libraries on the agents themselves. To achieve this I would need to copy the build artifacts that are built inside the container back into the host.
Is that possible?
回答1:
In order to copy a file from a container to the host, you can use the command
docker cp <containerId>:/file/path/within/container /host/path/target
Here's an example:
[jalal@goku scratch]$ sudo docker cp goofy_roentgen:/out_read.jpg .
Here goofy_roentgen is the name I got from the following command:
[jalal@goku scratch]$ sudo docker ps
[sudo] password for jalal:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1b4ad9311e93 bamos/openface "/bin/bash" 33 minutes ago Up 33 minutes 0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp goofy_roentgen
回答2:
Mount a "volume" and copy the artifacts into there:
mkdir artifacts
docker run -i -v ${PWD}/artifacts:/artifacts ubuntu:14.04 sh << COMMANDS
# ... build software here ...
cp <artifact> /artifacts
# ... copy more artifacts into `/artifacts` ...
COMMANDS
Then when the build finishes and the container is no longer running, it has already copied the artifacts from the build into the artifacts
directory on the host.
EDIT:
CAVEAT: When you do this, you may run into problems with the user id of the docker user matching the user id of the current running user. That is, the files in /artifacts
will be shown as owned by the user with the UID of the user used inside the docker container. A way around this may be to use the calling user's UID:
docker run -i -v ${PWD}:/working_dir -w /working_dir -u $(id -u) \
ubuntu:14.04 sh << COMMANDS
# Since $(id -u) owns /working_dir, you should be okay running commands here
# and having them work. Then copy stuff into /working_dir/artifacts .
COMMANDS
回答3:
Mount a volume, copy the artifacts, adjust owner id and group id:
mkdir artifacts
docker run -i --rm -v ${PWD}/artifacts:/mnt/artifacts centos:6 /bin/bash << COMMANDS
ls -la > /mnt/artifacts/ls.txt
echo Changing owner from \$(id -u):\$(id -g) to $(id -u):$(id -u)
chown -R $(id -u):$(id -u) /mnt/artifacts
COMMANDS
回答4:
tldr;
$ docker run --rm -iv${PWD}:/host-volume my-image sh -s <<EOF
chown $(id -u):$(id -g) my-artifact.tar.xz
cp -a my-artifact.tar.xz /host-volume
EOF
Longer...
docker run
with a host volume, chown
the artifact, cp
the artifact to the host volume:
$ docker build -t my-image - <<EOF
> FROM busybox
> WORKDIR /workdir
> RUN touch foo.txt bar.txt qux.txt
> EOF
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM busybox
---> 00f017a8c2a6
Step 2/3 : WORKDIR /workdir
---> Using cache
---> 36151d97f2c9
Step 3/3 : RUN touch foo.txt bar.txt qux.txt
---> Running in a657ed4f5cab
---> 4dd197569e44
Removing intermediate container a657ed4f5cab
Successfully built 4dd197569e44
$ docker run --rm -iv${PWD}:/host-volume my-image sh -s <<EOF
chown -v $(id -u):$(id -g) *.txt
cp -va *.txt /host-volume
EOF
changed ownership of '/host-volume/bar.txt' to 10335:11111
changed ownership of '/host-volume/qux.txt' to 10335:11111
changed ownership of '/host-volume/foo.txt' to 10335:11111
'bar.txt' -> '/host-volume/bar.txt'
'foo.txt' -> '/host-volume/foo.txt'
'qux.txt' -> '/host-volume/qux.txt'
$ ls -n
total 0
-rw-r--r-- 1 10335 11111 0 May 7 18:22 bar.txt
-rw-r--r-- 1 10335 11111 0 May 7 18:22 foo.txt
-rw-r--r-- 1 10335 11111 0 May 7 18:22 qux.txt
This trick works because the chown
invocation within the heredoc the takes $(id -u):$(id -g)
values from outside the running container; i.e., the docker host.
The benefits over docker cp
are:
- you don't have to
docker run --name
your container before
- you don't have to
docker container rm
after
回答5:
You do not need to use docker run
You can do it with docker create
From the docs
The docker create command creates a writeable container layer over the specified image and prepares it for running the specified command. The container ID is then printed to STDOUT. This is similar to docker run -d except the container is never started.
So, you can do
docker create -ti --name dummy IMAGE_NAME bash
docker cp dummy:/path/to/file /dest/to/file
docker rm -fv dummy
Here, you never start the container. That looked beneficial to me.
回答6:
If you don't have a running container, just an image, and assuming you want to copy just a text file, you could do something like this:
docker run the-image cat path/to/container/file.txt > path/to/host/file.txt
回答7:
I am posting this for anyone that is using Docker for Mac.
This is what worked for me:
$ mkdir mybackup # local directory on Mac
$ docker run --rm --volumes-from <containerid> \
-v `pwd`/mybackup:/backup \
busybox \
cp /data/mydata.txt /backup
Note that when I mount using -v
that backup
directory is automatically created.
I hope this is useful to someone someday. :)
回答8:
Most of the answers do not indicate that the container must run before docker cp
will work:
docker build -t IMAGE_TAG .
docker run -d IMAGE_TAG
CONTAINER_ID=$(docker ps -alq)
# If you do not know the exact file name, you'll need to run "ls"
# FILE=$(docker exec CONTAINER_ID sh -c "ls /path/*.zip")
docker cp $CONTAINER_ID:/path/to/file .
docker stop $CONTAINER_ID
回答9:
As a more general solution, there's a CloudBees plugin for Jenkins to build inside a Docker container. You can select an image to use from a Docker registry or define a Dockerfile to build and use.
It'll mount the workspace into the container as a volume (with appropriate user), set it as your working directory, do whatever commands you request (inside the container).
You can also use the docker-workflow plugin (if you prefer code over UI) to do this, with the image.inside() {} command.
Basically all of this, baked into your CI/CD server and then some.
回答10:
docker run -dit --rm IMAGE
docker cp CONTAINER:SRC_PATH DEST_PATH
https://docs.docker.com/engine/reference/commandline/run/
https://docs.docker.com/engine/reference/commandline/cp/
回答11:
If you just want to pull a file from an image (instead of a running container) you can do this:
docker run --rm <image> cat <source> > <local_dest>
This will bring up the container, write the new file, then remove the container. One drawback, however, is that the file permissions and modified date will not be preserved.
回答12:
Create a path where you want to copy the file and then use:
docker run -d -v hostpath:dockerimag
回答13:
I used PowerShell (Admin) with this command.
docker cp {container id}:{container path}/error.html C:\\error.html
Example
docker cp ff3a6608467d:/var/www/app/error.html C:\\error.html
回答14:
Create a data directory on the host system (outside the container) and mount this to a directory visible from inside the container. This places the files in a known location on the host system, and makes it easy for tools and applications on the host system to access the files
docker run -d -v /path/to/Local_host_dir:/path/to/docker_dir docker_image:tag