Docker Swarm Deploy a local Dockerfile - docker

I am trying to deploy a stack of services in a swarm on a local machine for testing purpose and i want to build the docker image whenever i run or deploy a stack from the manager node.
Is it possible what I am trying to achieve..

On Docker Swarm you can't build an image specified in a Docker Compose file:
Note: This option is ignored when deploying a stack in swarm mode with a (version 3) Compose file. The docker stack command accepts only pre-built images. - from docker docs
You need to create the image with docker build (on the folder where the Dockerfile is located):
docker build -t imagename --no-cache .
After this command the image (named imagename) is now available on the local registry.
You can use this image on your Docker Compose file like the following:
version: '3'
services:
example-service:
image: imagename:latest

You need to build the image with docker build. Docker swarm doesn't work with tags to identify images. Instead it remembers the image id (hash) of an image when executing stack deploy, because a tag might change later on but the hash never changes.
Therefore you should reference the hash of your image as shown by docker image ls so that docker swarm will not try to find your image on some registry.
version: '3'
services:
example-service:
image: imagename:97bfeeb4b649

While updating a local image you will get an error as below
image IMAGENAME:latest could not be accessed on a registry to record
its digest. Each node will access IMAGENAME:latest independently,
possibly leading to different nodes running different
versions of the image.
To overcome this issue start the service forcefully as follows
docker service update --image IMAGENAME:latest --force Service Name
In the above example it is as
docker service update --image imagename:97bfeeb4b649 --force Service Name

Related

Commands are not working in Ubuntu container

I have created a container using the following command: docker container run -i ubuntu. However, when I try to run a command within the container, such as cd, I get the following error: bash: line 1: cd: $'bin\r': No such file or directory. What could be the issue?
When you docker run an image, or use an image in a Dockerfile FROM line, or name an image: in a Docker Compose setup, Docker first checks to see if you have that image locally. If you have that image, Docker just uses it without checking Docker Hub or the other upstream registry.
Meanwhile, you can docker build or docker tag an image with any name you want...even a name that matches an official Docker Hub image.
You mention in a comment that you at some point did run docker build -t ubuntu .... That replaces the ubuntu image with what you built, so when you later docker run ubuntu, it's running your modified image and not the official Docker Hub Ubuntu image.
This is straightforward to fix. If you
docker rmi ubuntu
it will delete your local (modified) copy, and the next time you use it, Docker will automatically pull it from Docker Hub. It should also work to
# Explicitly get the Docker Hub copy of the image
docker pull ubuntu
# Build a custom image, pulling whatever's in the FROM line
docker build --pull -t my/image .
(You can also hit this in a Docker Compose setup if you specify both image: and build:; this instructs Compose on an explicit name to use for the built image. You do not need to repeat the FROM line in image:, and it causes trouble if you do. The resolution is the same as described above. I might leave image: out entirely unless you're planning to push the image to a registry.)

Update Jenkins running on docker container

I have a Jenkins running on Docker container and local docker registry.
docker-compose up
it does't go out side network rather pulls the image from local registry.
Is there a way i can update my local docker registry with latest Jenkins image?
And when i run docker-compose up i have latest Jenkins? Thank you!
So by default docker nature is always look for image available on host-machine and if not specific tag is provided it will search for default tag which is latest .
So in your case when you already have latest jenkins image available on host docker-compose will always use that image pretending this is the latest one. For using latest image available from registry you need to clean/delete jenkins image from your host who is having latest tag.
Delete and use latest jenkins image:
docker rmi -f jenkins:latest
docker-compose stop
docker-compose rm -f
docker-compose pull
docker-compose up -d
this is your private registry so you need to login to it:
docker login my-server.test:5000

How to build docker images using docker-compose

Let say I have a docker hub repository my_registry/project_name_service1.
I would like to build my docker images with the following repository name my_registry/project_name_service1
e.g docker-compose.yml
service1:
image: my_registry/project_name_service1
when I build the images using docker-compose build service1
the repository name becomes project_name_service1
where the prefix project_name is set in .env file COMPOSE_PROJECT_NAME=project_name
Now
how can I get my_registry/project_name_service1 as repository name for the docker image when I use docker-compose build service1
so that I can use docker-compose push service1 to push the image to the docker registry (say docker hub)
Provide container name value to your docker image with container_name : my_registry/project_name_service
See this documentation: https://docs.docker.com/compose/compose-file/#container_name
I think you are making a bit of a confusion regarding the terms.
You have images and you have containers. Each of them have names.
An image name is <repository>/<image_tag>:<image_version>.
A container name can be anything.
When you pull or push images, the part decides from which or to which repository to pull or push.
In docker-compose.yml you define your services.
If you only define "image" for a service, but no build context, then nothing will be build. The image will be downloaded when you run "docker-compose up"
If you define a build context ("build"), then docker-compose will build an image based on that context and then tag it with the name you specify in "image".
COMPOSE_PROJECT_NAME is used by "docker-compose up" to name the containers, not the images.
You can also re-tag an image with a docker command if you need it.
I hope this clarifies a bit more and you understand how to configure your docker-compose file. If you still have issues drop me a comment.

Docker stack deploy latest image works even when image is deleted

I have a docker compose file with a container that uses the latest tag:
code_site:
image: code_site:latest
deploy:
restart_policy:
condition: any
volumes:
- ../../data_to_backup/code_site/drupal_sites:/drupal_www/sites
- drupal_core:/drupal_www/core
- php_fpm_socket:/var/run/php-fpm7
networks:
- main_net
I have a process which will rebuild the container. I use it when I want to make changes to my site.
I am investigating a problem where the docker stack deploy command:
docker stack deploy --compose-file=docker-compose.yml code_site
(The stack name happens to match the image name but this is a coincidence.)
If I go through the following process:
Delete the code_site:latest image (rmi code_site:latest)
Rebuild a new code_site:latest image
Redeploy the stack
It will bring up the OLD version of the container. This is confusing, especially as I have deleted the old version.
I have gone further and I deleted the code_site image then I ran the stack deploy command.
The stack deploys successfully still running the old version of the container.
I can use the docker images command and verify that there is no container named code_site:latest so I have no idea how the stack could possibly deploy.
Can anyone explain how the image is coming back from the dead, and what method I should use to get rid of it permanently and force docker stack to use the real image?
Thanks
Robert
Update 1
code_site is a locally built image
I am running on a swarm but there is only one node in the swarm
Docker stack deploy will pull the latest image from your docker registry, since '--resolve-image always' is set by default, therefore always resolving to the latest image. If you don't want this run
docker stack deploy --resolve-image never [rest of deploy command]
However, to make it easier to maintain changes, I would suggest using version tags for your images in your registry, such as code_site:v1 when code changes push new version tagged code_site:v2 and deploy the new image/version using the normal deploy command without --resolve-image never.
Also if you plan to add nodes to your swarm you will need to change your command to docker stack deploy --with-registry-auth to allow the other nodes to pull the image from your repo.
Update 1
If you are 100% sure you do not have an image in your docker registry with the name code_site:latest then
this should work
Run:
docker rm $(docker ps -aq)
docker volume rm $(docker volume ls --format {{.ID}})
To check for lingering containers/services:
List Existing Services
docker service ls
List Running Stacks
docker stack ls
List All Containers
docker ps -aq
Then redeploy with deploy command
Alternatively to update your service without removing old containers/volumes/images, you can just update your image, then update your service without removing anything.
This will update your service using the new image... no need to stop, remove, then update... Just update.
Docker Service Update Command
Run after new image is built:
docker service update [SERVICE NAME] --image [IMAGE NAME] --force

How to convert docker-compose setup to docker image?

How to convert docker-compose setup to docker image?
So i have a docker enviroment setup with docker-compose and i would like to create a docker image for Docker Hub from that setup.
Is there a way of doing this ?
No, you can't merge multiple images.
You can capture running containers as images with docker commit, and push each image to the Hub - but you'd need to share your docker-compose.yml separately.
There is a new workflow for this type of scenario called application bundles, which lets you capture a distributed system as a bundle of images. It's currently an experimental feature.
You can either build the image with $ docker build command and use the correct tag and push it with $ docker push. Or you can define the correct image in docker-compose.yml:
container:
build: .
image: username/image:tag
And after the build push the image with $ docker-compose push

Resources