Docker toolbox volumes on windows doesn't refresh changes on container - docker

I am starting with docker on windows and I am trying to use volumes for manage data in containers.
My host environment is a:
Windows 8.1
Docker Toolbox 1.8.
Virtual Box 5.0.6
I've created a ngnix image using the following Dockerfile.
Dockerfile
FROM centos:6.6
MAINTAINER afym
ENV WEBPORT 80
RUN yum -y update; yum clean all
RUN yum -y install epel-release; yum clean all
RUN yum -y install nginx; yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
VOLUME /usr/share/nginx/html
EXPOSE $WEBPORT
CMD [ "/usr/sbin/nginx" ]
I've created a ngnix container using the following command.
docker run -d --name nge -v //c/Users/src:/usr/share/nginx/html -p 8082:80 ng1
b738fef9cc4d135416a8cca4caf869acf944319b7c3c61129b11f37f9d891598
Then I go to my browser and I can see the web page:
However when I make a change on my index.html file it doesn't refresh on browser
Editing my file
On my browser (ctrl + f5)
I went to the VirtualBox machine to check if my shared directories options is ok.
Then I inspect my nge container with the following command.
docker inspect ng1
Docker inspect
What is happening with volumes? Why I can not see my changes?

After a couple of days I could find the solution.
Firstable docker on windows even on MAC uses a boot2docker instance on VirtualBox.
Diagrams
On MAC
On Windows
Next, the official docker's documentation says :
docker volume
Docker Machine tries to auto-share your /Users (OS X) or C:\Users (Windows) directory
However, after find a solution I decided to change the default c/Users to another path just for keep order. With this in mind I did the following steps:
Define your own workspace directory. In my case is /e/arquitectura (optional. If you want you can use the default path which is /c/Users)
Verify the configuration on the Virtual Machine (In default machine go to > Configuration > Share directories)
Join to the default machine and mount the directory using the alias name
sudo mount -t vboxsf alias-name-virtualbox some-path-in-boot2docker
# In my case (boot2docker instance)
$ cd
$ mkdir arquitectura
$ sudo mount -t vboxsf arquitectura /arquitectura
Finally create a new container or restart an existing one if you haven't changed the c/user/ path
# In my case (docker client)
$ docker run -d --name nge -v //arquitectura/src:/usr/share/nginx/html -p 8081:80 ng1
Now it works.

Related

Running PHP, Apache and MySQL with Docker & docker-compose

I can't figure out how to use my containers after they are running in Docker (through docker-compose).
I've been reading up on Docker for the last few weeks and I'm interested in building an environment that I could develop on that and I could replicate efficiently to collaborate with my colleagues.
I've read through the following articles:
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-centos-7
https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-and-phpmyadmin-with-docker-compose-on-ubuntu-14-04
https://www.digitalocean.com/community/tutorials/how-to-work-with-docker-data-volumes-on-ubuntu-14-04
I've installed Docker and Docker Compose through a Bash script made up of the commands found in the previous articles: (Run as sudo)
## Install Docker package
function docker_install {
echo "__ installing docker"
# Run installer script
wget -qO- https://get.docker.com/ | sh
# Add user parameter to docker group
usermod -aG docker $1
# Enable docker on boot
sudo systemctl enable docker.service
# Start docker now
sudo systemctl start docker.service
}
## Install docker-compose package
function docker-compose_install {
echo "__ installing docker-compose"
# Update yum repo
sudo yum install epel-release
# Install pip with "yes" flag
sudo yum install -y python-pip
# Install SSL Extension
sudo pip install backports.ssl_match_hostname --upgrade
# Install docker-compose through pip
sudo pip install docker-compose
# Upgrade python
sudo yum upgrade python*
}
# Call Functions
docker_install
docker-compose_install
And I have a docker-compose.yml file for my Docker images. (For now I'm only pulling PHP and Apache as a proof-of-concept, I will include MySQL once can get PHP and Apache working together)
php:
image: php
links:
- httpd
httpd:
image: httpd
ports:
- 80:80
I call a sudo docker-compose up -d and I don't receive any errors:
Creating containerwrap_httpd_1
Creating containerwrap_php_1
Any my question is:
When I run a php -v and service httpd status after the images are running I receive:
-bash: php: command not found
and
● httd.service
Loaded: not-found (Reason: No such file or directory)
Active: inactive (dead)
If the images are running why am I not able to use PHP or see the status of Apache? How am I supposed to utilize my PHP and Apache containers?
Update
I've asked a more informed version of this question again.
What you are missing is that containers are like different machines. Running the commands at your droplet, you will not see anything running in those machines. You need to connect to them. One easy way is to use something:
docker exec -it CONTAINER_ID /bin/bash. This will give you access to each containers bash.
For your Apache server that would be containerwrap_httpd_1 and it will always change unless you have your docker-compose.yaml set up to use a constant name each time the service is created and started. Of course you can either curl localhost or open a browser and browse to your Droplet's IP address, provided it forwards http on the default port(or use the forwarding port). This will have the effect to see the Apache's default web page, because you have set up the export 80:80 rule for the service.
Seems you have some misunderstanding of Docker's concepts. You can image that each docker container as a lightweight Virtual Machine(of course Docker container is different with real VM). So basically after you created php and httpd containers, these php and httpd commands only available in the containers' bash. You cannot perform these commands in your host, because your host is a different machine from your containers. If you want to attach to the container bash, check out this command exec. You should be able to run php or httpd commands in the containers' bash.
If you want connect to your php container from your host, you can try docker run -p parameter, which will publish a container's port(s) to the host.
Or you want connect your php and httpd containers together, you should consider to read docker's network documents to figure out how to use link or docker network.

docker inside docker container

I want to install docker inside a running docker container.
docker run -it centos:centos7
My base container is using centos, I can login to running container using docker exec. But when I try to install docker inside it using yum install -y docker it installs.
But somehow I can't start the docker service with docker -d &, it gives me error as:
INFO[0000] Option DefaultNetwork: bridge
WARN[0000] Running modprobe bridge nf_nat br_netfilter failed with message: , error: exit status 1
FATA[0000] Error starting daemon: Error initializing network controller: Error initializing bridge driver: Setup IP forwarding failed: open /proc/sys/net/ipv4/ip_forward: read-only file system
Is there a way I can install docker inside docker container or build image already having running docker? I have already seen these examples but none works for me.
The output of uname -r on the host machine:
[fedora# ~]$ uname -r
4.2.6-200.fc22.x86_64
Any help would be appreciated.
Thanks in advance
Update
Thanks to https://stackoverflow.com/a/38016704/372019 I want to show another approach.
Instead of mounting the host's docker binary, you should copy or install a container specific release of the docker binary. Since you're only using it in a client mode, you won't need to install it as a system service. You still need to mount the Docker socket into the container so that you can easily communicate with the host's Docker engine.
Assuming that you got a base image with a working Docker binary (e.g. the official docker image), the example now looks like this:
docker run\
-v /var/run/docker.sock:/var/run/docker.sock\
docker:1.12 docker info
Without actually answering your question I'd suggest you to read Using Docker-in-Docker for your CI or testing environment? Think twice.
It explains why running docker-in-docker should be replaced with a setup where Docker containers run as siblings of the "outer" or "base" container. The article also links to the original https://github.com/jpetazzo/dind project where you can find working examples how to run Docker in Docker - in case you still want to have docker-in-docker.
An example how to enable a container to access the host's Docker daemon look like this:
docker run\
-v /var/run/docker.sock:/var/run/docker.sock\
-v /usr/bin/docker:/usr/bin/docker\
busybox:latest /usr/bin/docker info
If you are on Mac with Docker toolbox.
The below command WON’T WORK
docker run\
-v /var/run/docker.sock:/var/run/docker.sock\
-v /usr/bin/docker:/usr/bin/docker\
busybox:latest /usr/bin/docker info
Because /var/run/docker.sock will not be on your OSX filesystem
the Docker daemon is running inside the boot2docker VM - and that's where the unix socket is.
So you have to run the container from boot2docker VM
$ docker-machine ssh default
$ docker run\
-v /var/run/docker.sock:/var/run/docker.sock\
-v $(which docker):/usr/bin/docker\
busybox:latest /usr/bin/docker info
$ exit
This looks like Docker-in-Docker, feels like Docker-in-Docker, but it’s not Docker-in-Docker, when this container will create more containers, those containers will be created in the top-level Docker.
You need the --privileged parameter.
By default, Docker containers are “unprivileged” and cannot, for
example, run a Docker daemon inside a Docker container.
Source
Run your base image with the command docker run --privileged -it centos:centos7 bash. Then you may install and run another docker container inside that container.
I`ve a similar problems in my vms.
I`ve solve the problem with change the storage file system from image to vfs(in daemon.json file)
like the image bellow
For image works first create a base image, in my case with centos7
FROM centos:7
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
with this image builded (in my case i called local/c7-systemd) create a second image, installing docker and moving daemon.json to inside.
FROM local/c7-systemd
RUN yum install -y yum-utils
RUN yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
RUN yum install -y docker-ce docker-ce-cli containerd.io
RUN curl -L "https://github.com/docker/compose/releases/download/1.28.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose
RUN ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
COPY daemon.json /etc/docker/daemon.json
RUN yum install -y nano
RUN systemctl enable docker
EXPOSE 80
EXPOSE 8080
EXPOSE 8161
EXPOSE 6379
EXPOSE 8761
CMD ["/usr/sbin/init"]
enjoy!

Running 2 services

I'm building an image for github's Linkurious project, based on an image already in the hub for the neo4j database. the neo image automatically runs the server on port 7474 and my image runs on port 8000.
when I run my image I publish both ports (could I do this with EXPOSE?):
docker run -d --publish=7474:7474 --publish=8000:8000 linkurious
but only my server seems to run. if I hit http://[ip]:7474/ I get nothing. is there something special I have to do to make sure they both run?
* Edit I *
here's my Dockerfile:
FROM neo4j/neo4j:latest
RUN apt-get -y update
RUN apt-get install -y git
RUN apt-get install -y npm
RUN apt-get install -y nodejs-legacy
RUN git clone git://github.com/Linkurious/linkurious.js.git
RUN cd linkurious.js && npm install && npm run build
CMD cd linkurious.js && npm start
* Edit II *
to perhaps help explain my quandary, I've asked a different question
EXPOSE is there to allow inter-containers communication (within the same docker daemon), with the docker run --link option.
Port mapping is there to map EXPOSEd ports to the host, to allow client-to-container communication. So you need --publish.
See also "Difference between “expose” and “publish” in docker".
See also an example with "Advanced Usecase with Docker: Connecting Containers"
Make sure though that the ip is the right one ($(docker-machine ip default)).
If you are using a VM (meaning, you are not using docker directly on a Linux host, but on a Linux VM with VirtualBox), make sure the mapped ports 7474 and 8000 are port forwarded from the host to the VM.
VBoxManage controlvm boot2docker-vm natpf1 "name,tcp,,7474,,7474"
VBoxManage controlvm boot2docker-vm natpf1 "name,tcp,,8000,,8000"
In the OP's case, this is using neo4j: see "Neo4j with Docker", based on the neo4j/neo4j/ image and its Dockerfile:
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["neo4j"]
It is not meant to be used for installing another service (like nodejs), where the CMD cd linkurious.js && npm start would completely override the neo4j base image CMD (meaning neo4j would never start).
It is meant to be run on its own:
# interactive with terminal
docker run -i -t --rm --name neo4j -v $HOME/neo4j-data:/data -p 8474:7474 neo4j/neo4j
# as daemon running in the background
docker run -d --name neo4j -v $HOME/neo4j-data:/data -p 8474:7474 neo4j/neo4j
And then used by another image, with a --link neo4j:neo4j directive.

docker toolbox mount file on windows

I am a beginner with docker and I am using a windows machine. But I have a problem mounting files using volumes. The documentation says the following thing about mount files on OSX and windows :
Official docker docs
Note: If you are using Docker Machine on Mac or Windows, your Docker daemon only has limited access to your OS X/Windows filesystem. Docker Machine tries to auto-share your /Users (OS X) or C:\Users (Windows) directory - and so you can mount files or directories using docker run -v /Users/<path>:/<container path> ... (OS X) or docker run -v /c/Users/<path>:/<container path ... (Windows). All other paths come from your virtual machine’s filesystem.
I have a small nginx Dockerfile:
FROM centos:6.6
MAINTAINER afym
ENV WEBPORT 80
RUN yum -y update; yum clean all
RUN yum -y install epel-release; yum clean all
RUN yum -y install nginx; yum clean all
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
VOLUME /usr/share/nginx/html
EXPOSE $WEBPORT
CMD [ "/usr/sbin/nginx" ]
Creating a simple container
docker run -d --name simple -p 8082:80 ng1
8875448c01a4787f1ffe4c4c5c492efb039e452eff957391ac52a08915e18d66
Creating a container with a volume
My windows host directory
Creating the docker container with -v option
docker run -d --name simple2 -v /c/Users/src:/usr/share/nginx/html -p 8082:80 ng1
invalid value "C:\\Users\\src;C:\\Program Files\\Git\\usr\\share\\nginx\\html"
for flag -v: bad mount mode specified
: \Program Files\Git\usr\share\nginx\html
See 'C:\Program Files\Docker Toolbox\docker.exe run --help'.
Inspecting the ng1 image
docker inspect ng1
What is wrong when I am creating a docker container with a volume?
Thanks.
Try to run it with additional / for volume like:
docker run -d --name simple2 -v /c/Users/src://usr/share/nginx/html -p 8082:80 ng1
Or even for host OS, as
docker run -d --name simple2 -v //c/Users/src://usr/share/nginx/html -p 8082:80 ng1
Due to this issue:
This is something that the MSYS environment does to map POSIX paths to Windows paths before passing them to executables.
As the OP said:
Official docker docs :
Note: If you are using Docker Machine on Mac or Windows, your Docker
daemon only has limited access to your OS X/Windows filesystem. Docker
Machine tries to auto-share your /Users (OS X) or C:\Users (Windows)
directory - and so you can mount files or directories using
docker run -v /Users/:/ ... (OS X)
or
docker run -v /c/Users/:/
But if you want access to other directories, you need to add a new shared folder to the virtual box settings (Settings > Shared Folders > Add share).
Add there a new share (only possible when you stop the vm before, docker-machine stop:
path C:\Projects
name c/Projects
autoMount yes
Or edit directly the vbox configuration file
C:\Users\<username>\.docker\machine\machines\default\default\default.vbox
Add there into <SharedFolders> the line
<SharedFolder name="c/Projects" hostPath="\\?\c:\Projects" writable="true" autoMount="true"/>
Restart the machine:
docker-machine stop
docker-machine start
Now, it's possible to mount also directories with the base C:\Projects
docker run -v //c/Projects/myApp://myApp <myImage>
For anyone using docker ~> 1.12 and faces this issue. I spent 30min trying to figure it out until i realized you have to specifically share a drive first via docker settings, see:
https://docs.docker.com/docker-for-windows/#/shared-drives
If you're simply looking to access a local drive, the MINGW32 Docker Toolbox terminal puts the root of each drive in /<drive-letter>, so drive C:\ will be at /c/

How to link binaries between docker containers

Is it possible to use docker to expose the binary from one container to another container?
For example, I have 2 containers:
centos6
sles11
I need both of these containers to have similar versions git installed. Unfortunately the sles container does not have the version of git that I need.
I want to spin up a git container like so:
$ cat Dockerfile
FROM ubuntu:14.04
MAINTAINER spuder
RUN apt-get update
RUN apt-get install -yq git
CMD /usr/bin/git
# ENTRYPOINT ['/usr/bin/git']
Then link the centos6 and sles11 containers to the git container so that they both have access to a git binary, without going through the trouble of installing it.
I'm running into the following problems:
You can't link a container to another non running container
I'm not sure if this is how docker containers are supposed to be used.
Looking at the docker documentation, it appears that linked containers have shared environment variables and ports, but not necessarily access to each others entrypoints.
How could I link the git container so that the cent and sles containers can access this command? Is this possible?
You could create a dedicated git container and expose the data it downloads as a volume, then share that volume with the other two containers (centos6 and sles11). Volumes are available even when a container is not running.
If you want the other two containers to be able to run git from the dedicated git container, then you'll need to install (or copy) that git binary onto the shared volume.
Note that volumes are not part of an image, so they don't get preserved or exported when you docker save or docker export. They must be backed-up separately.
Example
Dockerfile:
FROM ubuntu
RUN apt-get update; apt-get install -y git
VOLUME /gitdata
WORKDIR /gitdata
CMD git clone https://github.com/metalivedev/isawesome.git
Then run:
$ docker build -t gitimage .
# Create the data container, which automatically clones and exits
$ docker run -v /gitdata --name gitcontainer gitimage
Cloning into 'isawesome'...
# This is just a generic container, but what I do in the shell
# you could do in your centos6 container, for example
$ docker run -it --rm --volumes-from gitcontainer ubuntu /bin/bash
root#e01e351e3ba8:/# cd gitdata/
root#e01e351e3ba8:/gitdata# ls
isawesome
root#e01e351e3ba8:/gitdata# cd isawesome/
root#e01e351e3ba8:/gitdata/isawesome# ls
Dockerfile README.md container.conf dotcloud.yml nginx.conf

Resources