I have a simple .dockerignore file with the following:
.git/
.idea/
venv/
My docker-compose.yml file mounts the volume:
version: "3"
services:
frontend:
build: .
command: ["gunicorn", "--bind", "0.0.0.0:8000", "project.app:create_app()"]
env_file:
- .env
volumes:
- .:/frontend
ports:
- "8000:8000"
Perhaps I don't understand the full syntax or intent of the .dockerignore file, but after running docker-compose up --build, .git/, .idea/ and venv/ end up in my container.
I've read up and saw this but it doesn't seem feasible that one cannot mount and prevent files and directories from landing in the container.
How do I prevent these directories from becoming available in the container?
The .dockerignore file will modify the context that is sent to the docker daemon to build the image. So the created image will not have these files inside unless you recreate them.
The volume mount is completely separate and a host volume mount, aka bind mount, will map the contents of the host directory directly into the container as is. This is a Linux OS level activity that doesn't follow .dockerignore.
You will need to exclude those files from the directory that you mount into the container, or not mount the volume into the container and rely on the image to take advantage of .dockerignore.
Related
I have a simple .dockerignore file with the following:
.git/
.idea/
venv/
My docker-compose.yml file mounts the volume:
version: "3"
services:
frontend:
build: .
command: ["gunicorn", "--bind", "0.0.0.0:8000", "project.app:create_app()"]
env_file:
- .env
volumes:
- .:/frontend
ports:
- "8000:8000"
Perhaps I don't understand the full syntax or intent of the .dockerignore file, but after running docker-compose up --build, .git/, .idea/ and venv/ end up in my container.
I've read up and saw this but it doesn't seem feasible that one cannot mount and prevent files and directories from landing in the container.
How do I prevent these directories from becoming available in the container?
The .dockerignore file will modify the context that is sent to the docker daemon to build the image. So the created image will not have these files inside unless you recreate them.
The volume mount is completely separate and a host volume mount, aka bind mount, will map the contents of the host directory directly into the container as is. This is a Linux OS level activity that doesn't follow .dockerignore.
You will need to exclude those files from the directory that you mount into the container, or not mount the volume into the container and rely on the image to take advantage of .dockerignore.
When i use docker-compose with volumes to sync my files from host to container i cant see any new files created in the dockerfile
my docker-compose.yml:
version: "3"
services:
web:
image: nginx:latest
volumes:
- ./:/code
links:
- php
php:
build: .
volumes:
- ./:/code
My dockerfile looks like this:
FROM php:7-fpm
WORKDIR /code
RUN touch testfile
Of course thats a simplified example, but why do I not see the "testfile" on my host System? if I use docker-compose exec php touch testfile everything works as expected, i see the testfile on my host.
From my understanding I do need to see it outside of my container for it to be shared with the other containers with the same volume (in this example nginx)
When you run RUN touch testfile within your Dockerfile it creates the testfile within the image itself.
Now when you start your container and volume mount your ./ directory to /code, it will mount over your existing /code folder in the image which is why you see it empty. If you didn't add the volume mount in your compose file, it would have the testfile in there.
Note: I don't fully understand your use case but if you wanted your image to create that file within the volume mount, you would need to add it to your entrypoint.
I am having problems with writing files out from inside a docker container to my host computer. I believe this is a privilege issue and prefer not to set privileged: True. A work around for writing out files is by pre-pending ../ to a volume in my docker-compose.yml file. For example,
version: '3'
services:
example:
volumes:
- ../:/example
What exactly is ../ doing here? Is it taking from the container's privileges and "going up" a directory to the host machine? Without ../, I am unable to write out files to my host machine.
Specifying a path as the source, as opposed to a volume name, bind mounts a host path to a path inside the container. In your example, ../ will be visible inside the container at /example on a recent version of docker.
Older versions of docker can only access the directory it is in and lower, not higher, unless you specify the higher directory as the context.
To run the docker build from the parent directory:
docker build -f /home/me myapp/Dockerfile
As opposed to
docker build -f /home/me/myapp Dockerfile
Doing the same in composer:
#docker-compose.yml
version: '3.3'
services:
yourservice:
build:
context: /home/me
dockerfile: myapp/Dockerfile
Or with your example:
version: '3'
services:
build:
context: /home/me/app
dockerfile: docker/Dockerfile
example:
volumes:
- /home/me/app:/example
Additionally you have to supply full paths, not relative paths. Ie.
- /home/me/myapp/files/example:/example
If you have a script that is generating the Dockerfile from an unknown path, you can use:
CWD=`pwd`; echo $CWD
To refer to the current working directory. From there you can append /..
Alternately you can build the image from a directory one up, or use a volume which you can share with an image that is run from a higher directory, or you need to output your file to stdout and redirect the output of the command to the file you need from the script that runs it.
See also: Docker: adding a file from a parent directory
The statement volumes: ['../:/example'] makes the parent directory of the directory containing docker-compose.yml on the host (../) visible inside the container at /example. Host directory bind-mounts like this, plus some equivalent constructs using a named volume attached to a specific host directory, are the only way a container can write out to the host filesystem.
When using compose for development I have my app mounted inside /var/www/html with this:
volumes:
- ./app:/var/www/html
My local copy needs all the images that are in the production website, that are quite a lot so I don't want to store them in my tiny ssd but in a big extenal disk.
So my images are located in my /media/storage/bigdisk/images.
it is possible to mount this location inside the already mounted /var/www/html?
This way doesn't seem to work:
volumes:
- ./app:/var/www/html
- /media/storage/bigdisk/images:/var/www/html/images
This should work normally, the only downside of this solution is that docker will create additional directory in ./app/images - so it can mount images volume.
For this directory tree:
- app
--- index.php
- docker-compose.yml
- media
--- picture.png
And docker-compose.yml:
version: '2'
services:
app:
image: ubuntu
volumes:
- ./app:/var/www/html
- ./media:/var/www/html/images
You get:
$ docker-compose run --rm app find /var/www/html
/var/www/html
/var/www/html/index.php
/var/www/html/images
/var/www/html/images/picture.png
This works even when ./app/images directory is present locally with some content. If it not exists then docker creates empty directory there with root:root persmission (if container runs as root).
Tested on Docker version 1.12.6 and docker-compose version 1.8.0
I've nignx container and one asset container which have all my assets build from grunt or some other tools.
Now in docker compose file, i want to mount asset container's 's folder path into nginx container so nginx can serve that files.
How can we do that? i don't remember but i think there is a option where we can share path of one container with another.
Suppose if i scale up nginx to 2 container then will that mount works for all instance of nginx?
if i scale up asset container then what will happen?
i also want to mount that with my host so development can be done be easily.
What you want to do is use a volume, and then mount that volume into whatever containers you want it to appear in.
Completely within Docker
You can do this completely inside of Docker.
Here is an example (stripped-down - your real file would have much more than this in it, of course).
version: '3'
services:
nginx:
volumes:
- asset-volume:/var/lib/assets
asset:
volumes:
- asset-volume:/var/lib/assets
volumes:
asset-volume:
At the bottom is a single volume defined, named "asset-volume".
Then in each of your services, you tell Docker to mount that volume at a certain path. I show example paths inside the container, just adjust these to be whatever path you wish them to be in the container.
The volume is an independent entity not owned by any particular container. It is just mounted into each of them, and is shared. If one container modifies the contents, then they all see the changes.
Note that if you prefer only one can make changes, you can always mount the volume as read-only in some services, by adding :ro to the end of the volume string.
services:
servicename:
volumes:
- asset-volume:/var/lib/assets:ro
Using a host directory
Alternately you can use a directory on the host and mount that into the containers. This has the advantage of you being able to work directly on the files using your tools outside of Docker (such as your GUI text editor and other tools).
It's the same, except you don't define a volume in Docker, instead mounting the external directory.
version: '3'
services:
nginx:
volumes:
- ./assets:/var/lib/assets
asset:
volumes:
- ./assets:/var/lib/assets
In this example, the local directory "assets" is mounted into both containers using the relative path ./assets.
Using both depending on environment
You can also set it up for a different dev and production environment. Put everything in docker-compose.yml except the volume mounts. Then make two more files.
docker-compose.dev.yml
docker-compose.prod.yml
In these files put only the minimum config to define the volume mount. We'll mix this with the docker-compose.yml to get a final config.
Then use this. It will use the config from docker-compose.yml, and use anything in the second file as an override or supplemental config.
docker-compose -f docker-compose.yml \
-f docker-compose.dev.yml \
up -d
And for production, just use the prod file instead of the dev file.
The idea here is to keep most of the config in docker-compose.yml, and only the minimum set of differences in the alternative files.
Example:
docker-compose.prod.yml
version: '3'
services:
nginx:
volumes:
- asset-volume:/var/lib/assets
docker-compose.dev.yml
version: '3'
services:
nginx:
volumes:
- ./assets:/var/lib/assets