How to convert docker-compose setup to docker image? - docker

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

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.)

Do I need to `docker commit` in order to push an image into a docker image registry (eg. docker hub)?

Usually according to docs In order to build a docker Image I need to follow these steps:
Create a Dockerfile for my application.
Run docker build . Dockerfile where the . is the context of my application
The using docker run run my image into a container.
Commit my image into a container
Then using docker push push the image into a container.
Though sometimes just launching the image into a container seems like a waste of time because I can tag my images using the parameter -t into the docker build command. So there's no need to commit a container as an image.
So is neseserily to commit a running container as an image?
You don't need to run and commit. docker commit allows you to create a new image from changes made on existing container.
You do need to build and tag your image in a way that will enable you to push it.
docker build -t [registry (defaults to docker hub)]/[your repository]:[image tag] [docker file context folder]
for example:
docker build -t my-repository/some-image:image-tag .
And then:
docker push my-repository/some-image:image-tag
This will build an image from a docker file found in the current folder (where you run the docker build command). The repository in this case is my-repository, the image name is some-image and it's tag is image-tag.
Also please note that you'll have to perform docker login with your credentials to docker hub before you are able to actually push the image.
You can also tag an existing image without rebuilding it. This is useful if you want to push an existing image to a different registry or if you want to create a different image tag. for example:
docker tag my-repository/some-image:image-tag localhost:5000/my-repository/some-image:image-tag
This will add a new tag to the image from the previous example. Note the registry part added (localhost:5000). If you call docker push on that tag (docker push localhost:5000/my-repository/some-image:image-tag) the image will be pushed to a registry found on localhost:5000 (of course you need the registry up and running before trying to push).
There's no need to do so. In order to prove that you can just tag the image and push it into the registry here's an example:
I made the following Dockerfile:
FROM alpine
RUN echo "Hello" > /usr/share/hello.txt
ENTRYPOINT cat /usr/share/hello.txt
Nothing special just generates a txt file and shows its content.
Then I can build my image using tags:
docker build . -t ddesyllas/dummy:201201241200 -t ddesyllas/dummy:201201241200
And then just push them to the registry:
$ docker push ddesyllas/dummy
The push refers to repository [docker.io/ddesyllas/dummy]
1aa99de3dbec: Pushed
6bc83681f1ba: Mounted from library/alpine
201908241504: digest: sha256:93e8407b1d52620aeadd769486ef1402b9e310018cae0972760f8c1a03377c94 size: 735
1aa99de3dbec: Layer already exists
6bc83681f1ba: Layer already exists
latest: digest: sha256:93e8407b1d52620aeadd769486ef1402b9e310018cae0972760f8c1a03377c94 size: 735
And as you can see from the output you can just build the tags and push it directly, good for your ci/cd pipeline. Though, generally speaking, you may need to launch the application into a container in order to do acceptance and other type of tests (eg. end-to-end tests).

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 Swarm Deploy a local Dockerfile

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

Docker - is it necessary to push images to remote server?

I have successfully built some Docker images:
Now I would like to start my microservices by docker-compose, unfortunatelly I am unable to pull those images i.e. repository callista/discovery-server not found: does not exist or no pull access I solved this error by logging into my DockerHub account and pushining those images to remote server. But it seems to me like a little overkill to send such larges images (which are likely to change pretty soon) over the Internet over and over again twice (push&pull).
Is it possible to configure Docker to install those images locally and not to pull from remote server?
I use Docker 1.8 and work on Windows 10.
Do you need to run this images in a server different from the one you build then?
If you need you have some alternatives:
As #engineer-dollery said, you can run a registry into your network, than you would not need to send it over the internet, only in your network. Docs: https://docs.docker.com/registry/deploying/
You could use the docker save and docker import to move then around too. Docs: https://docs.docker.com/engine/reference/commandline/save/
But if the server you run the images is the same you build then...
...than you could just add the tag image to your docker-compose services, and do a docker-compose build, as #lauri said, but with the image docker-compose will create a image with that name after the build, and then you could do docker run using than. Or do a docker-compose up --build so it will always build than again if something changes into the Dockerfile
If you define build option in docker-compose.yml, you should be able to build images locally with Docker Compose and then it uses those images without pulling. By default Docker Compose builds images if they are not found locally. If you want to rebuild images just add --build option docker-compose up command docker-compose up --build
Docker Compose build reference:
https://docs.docker.com/compose/compose-file/#build

Resources