Docker-Compose Issue with container name - docker

I have created a docker image with required packages. I have run the docker image specifying the host and guest port along with the required volume mounting
Example:
sudo docker run -it --name CONTAINERNAME -v /host:/guest -p
hostportno:guestportno
My container is up and running fine.
I am trying to migrate my container to a new docker image using docker-compose.
I have created docker-compose.yml file and specified the required parameters as shown below:
image: test1
ports
- "1234:123"
- "2000:223"
volumes:
- /home:/test
-container_name: dockercomposetest
working_dir: /test
command: /bin/bash
I am unable to migrate it using docker-compose.
I am getting issue as stated below:
Conflict. The name "test" is already in use by container eeedac72bb25.
You have to delete (or rename) that container to be able to reuse that
name.
Work around currently is I have to stop and remove the container and perform docker-compose up.
Can I not restart/migrate a container using docker-compose with same name as I have started in normal docker run process.

No, you can't have two containers with the same name. You'll have to pick a different name for the container_name field. The previous container needs to be removed before you can re-use the name.
If you wanted Compose to treat the container as if it had created it, you have to set the container labels as Compose does. The easiest way to find these would be to have compose create a container (probably by removing the container_name field), then using docker inspect to view the labels.

Related

docker-compose vs creating and running an image

I'm new to docker and trying to understand what's best for my project (a webapp).
So far, I understand that I can either :
use docker-compose up -d to start a container defined by a set of rule in a docker-compose.yaml
build an image from a dockerfile and then create a container from this image
If I understand correctly, docker-compose up -d allows me (via volumes) to mount files (e.g my application) into the container. If i build an image however, I am able to embed my application natively in it (with a Dockerfile and COPY instruction).
Is my understanding correct ? How should I choose between those 2 choices ?
Docker Compose is simply a convenience wrapper around the docker command.
Everything you can do in docker compose, you can do plainly with running docker.
For example, these docker commands:
$ docker build -t temp .
$ docker run -i -p 3000:80 -v $PWD/public:/docroot/ temp
are similar to having this docker compose file:
version: '3'
services:
web:
build: .
image: temp
ports: ["3000:80"]
volumes:
- ./public:/docroot
and running:
$ docker-compose up web
Although docker compose advantages are most obvious when using multiple containers, it can also be used to start a single container.
My advice to you is: Start without docker compose, to understand how to build a simple image, and how to run it using the docker command line. When you feel comfortable with it, take a look at docker compose.
As for the best practice in regards to copying files to the container, or mounting them - the answer is both, and here is why:
When you are in development mode, you do not want to build the image on every code change. This is where the volume mount comes into play. However, your final docker image should contain your code so it can be deployed anywhere else. After all, this is why we use containers right? This is where the COPY comes into play.
Finally, remember that when you mount a volume to the container, it will "shadow" the contents of that folder in the container - this is how using both mount and COPY actually works as you expect it to work.
Docker-compose is just a container orchestrator.
I just provides you a simple way to create multiple related containers. The relationship between containers can be volumes, networks, start order, environment variables, etc.
In background, docker-compose uses plain docker. So, anything you can do using docker-compose (mounting volumes, using custom networks, scaling) can be done using docker commands (but of course is harder).

How to start a existing mysql container in docker (toolbox)?

I have a container (i'm using this container https://hub.docker.com/_/mysql/) which had started before, with ID 5f96e9570d1b1475a888d7a615acdd9a7715c1ed6f0c40900f2e9c1ab485c7cf, but now how can i restart it ? I tried this command but not work
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=*Abcd1234 -d mysql:5.7
D:\CWindow10\Docker Toolbox\docker.exe: Error response from daemon: Conflict. The container name "/mysql" is already in use by container "5f96e9570d1b1475a888d7a615acdd9a7715c1ed6f0c40900f2e9c1ab485c7cf". You have to remove (or rename) that container to be able to reuse that name.
See 'D:\CWindow10\Docker Toolbox\docker.exe run --help'.
If i delete the container and retype the command, will the old data still exist in new container?
To restart an existing container, simply run docker start <container_name_or_id>.
Regarding the data: docker uses the concept of volumes to put data. For the mysql image, there's a section "Where to Store Data" on the docker hub site. If you don't manually declare where the image should go, docker will create one for you. If you want your data to be kept, the easiest way is to create a folder and tell the docker run command to map that volume. That way, you can still use it if you throw away your container.
use this command to restart container docker restart <CONTAINER>
starting new container will not preserve your data unless you have mounted external volume and stored data on it. Have a look at this blog http://blog.arungupta.me/docker-mysql-persistence/

Rename a project by keeping containers

I decided to change the project name of a docker composition:
$ docker-compose -p old_name up -d # Before
Starting old_name_web_1
$ docker-compose -p new_name up -d # After
Creating new_name_web_1
But I don't wanted to delete my containers, so I renamed them:
$ docker rename old_name_web_1 new_name_web_1
...
I thought docker-compose was based on container names, but it does not seem to be the case:
$ docker-compose -p new_name up -d
ERROR: for web Cannot create container for service web: Conflict. The name "/new_name_web_1" is already in use by container 4930deaabb[...]. You have to remove (or rename) that container to be able to reuse that name.
ERROR: Encountered errors while bringing up the project.
How can I relink my old containers to the new composition ?
It looks like you are using one of the newer versions of docker compose which tracks containers by labels assigned to them rather than by their names. That is why renaming the container didn't work.
Updating labels
You can check container's labels through the docker inspect command.
$ docker inspect --format='{{json .Config.Labels }}' container_name
The project name is the value of the 'com.docker.compose.project' label.
Moving an existing container to a new project is as easy as changing the value of that label. However it is not yet supported by Docker CLI. There is an open issue requesting that feature.
Workaround
It still can be achieved by directly editing the configuration file of that particular container. There you will find labels currently assigned to that container.
$ nano /var/lib/docker/containers/$container_id/config.v2.json
Assign the new project name to the 'com.docker.compose.project' label and save the file. Next you have to restart the daemon. Otherwise the changes will not be visible to docker.
$ systemctl daemon-reload
While it is true docker-compose reuse existing containers, this comment mentions:
docker-compose by default uses the folder name of the yml file as the project name, and prefix that name to all container names.
This could explain why docker-compose up did not pick up the new container name.

How to stop/relaunch docker container without losing the changes?

I did the following and lost all the changed data in my Docker container.
docker build -t <name:tag> .
docker run *-p 8080:80* --name <container_name> <name:tag>
docker exec (import and process some files, launch a server to host them)
Then I wanted to run it on a different port. docker stop & docker run does not work. Instead I did
docker stop
docker rm <container_name>
docker run (same parameters as before)
After the restart I saw the changes that happened in the container at 1-3 had disappeared, and had to re-run the import.
How do I do this correctly next time?
what you have to do is build the image from the container you just stopped after making changes. Because your old command still using the old image which doesn't have new changes(you have made changes in container which you just stopped not in image )
docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
docker commit -a me new_nginx myrepo/nginx:latest
then you can start container with the new image you just built
but if you dont want create image with the changes you made(like you dont want to put config containing password in the image) you can use volume mount
docker run -d -P --name web -v /src/webapp:/webapp training/webapp python app.py
This command mounts the host directory, /src/webapp, into the container at /webapp. If the path /webapp already exists inside the container’s image, the /src/webapp mount overlays but does not remove the pre-existing content. Once the mount is removed, the content is accessible again. This is consistent with the expected behavior of the mount command.
Manage data in containers
Every time you do a docker run it will spin up a fresh container based on your image. And once a container is started, there are very few things that docker allows you to change with the docker update. So instead, you should preserve your data in an external volume that needs to persist between instances of a container. E.g.
docker run -p 8080:80 -v app-data:/data --name <container_name> <name:tag>
The volume name (app-data) and mount point in the container (/data) can be changed for your own requirements. Then when you destroy and restart a new container, you can mount the same volume in the new container.

Equivalent of local host files for running Bluemix containers

When running a docker container locally you can run it with a command like this:
docker run --name some-nginx -v /some/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx
This will use the file /some/nginx.conf in place of /etc/nginx/nginx.conf within your running docker container. This is very handy if you don't want to permanently enshrine your configuration files inside of an image.
However, when running Bluemix containers there is no local filesystem as everything is on a remote host. Is there an equivalent option available?
Without this it seems like the best options are either to build a dedicated image with your configuration or to put the entire configuration as a user provided service. Is this a correct assumption?
You can create a volume and add the configuration files you want to persist on it. The volume is not deleted when a container instance is removed and it can be used by multiple containers.
To create a volume you can use the following command:
$ cf ic volume create my_volume
Then you can create a new container and mount the volume to a path in the container, for example:
$ cf ic run -v my_volume:/path/to/mount --name my_container my_image
You can find more details in the following documentation link:
https://console.ng.bluemix.net/docs/containers/container_creating_ov.html#container_volumes_ov

Resources