How to build docker images using docker-compose - docker

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.

Related

How to run a Docker Compose image pulled from GitHub Packages

I have pushed a Docker image on GitHub Packages and now I would like to pull it and use it.
To run the image locally, I used to go to the related folder and run it with the command docker-compose up.
However now, by pulling from GitHub Packages, I just get the Docker image without any folder and I don't know how I can run it.
By inspecting the image it has all the files related to the original folder but, when I try to run the docker-compose up ghcr.io/giuliomat/bdt-project command, I get an error saying that there is no docker-compose.yml in the directory. If I just use the command docker run ghcr.io/giuliomat/bdt-project it runs one of the two services specified in the docker-compose.yml file. How can I run the Docker Compose image correctly? Thanks in advance!
Update: I try to explain myself better. In the image there is a Dockerfile (that now I've uploaded in the question) which is used to build the web service. I developed the image locally and I have no problem running it with docker-compose up, but now I wanted to see what it has to be done in order to run it when a user pulls it from my GitHub Packages, and this is my problem. The pulled image should have all the elements needed to run but I don't know what command to use in order to tell Docker to run both services specified in the docker-compose.yml file, since when a user pulls from GitHub Packages it only gets the image and no folder where run docker-compose up.
Dockerfile:
docker-compose.yml:
content of the pulled docker image:
Update:
Docker image repository does not store yml files, therefore either you provide a README.md for the user in the image registry (with yml verbosely copy-pasted there) and/or you provide also the link to the version control repository where the rest of the files reside, so the user can clone and use docker-compose up.
docker-compose up [options] [--scale SERVICE=NUM...] [SERVICE...] means "find [service...](if specified, otherwise run all) indocker-compose.yml` in the current working directory and run it.
So if you move out of the folder with docker-compose.yml it won't pick the compose file and therefore won't work.
Also for the image using you need to specify image property of a service instead of build because build works with the Dockerfile locally and attempts to build an image instead of pulling it from GitHub Docker image registry:
web:
image: "ghcr.io/giuliomat/bdt-project:latest"
It'd be the same way you have it for redis service.
Also make sure you can pull the image locally first (otherwise docker login would be necessary prior to compose commands) by:
docker pull ghcr.io/giuliomat/bdt-project

Which command should I use to build and push my entire dockerised app and its services to docker hub? docker or docker-compose?

I am a little bit confused when using docker and docker-compose:
With dockerfile I can build, run, and push the docker application image to docker hub in order to allow other people to download and run it on their local computers.
With Docker-compose I can build, run and push the service image ( eg: redis, cassandra, etc)
My concern:
I got an application folder with the following files:
- main.go # the main app in Golang
- Dockerfile # container definition file
- Docker-compose.yml # contains all the services ( Redis and Cassandra)
which command should I use to build and push my entire app and its services on the docker hub? docker or docker-compose?
One useful conceptual way to think about this is that the docker-compose.yml file specifies a set of docker build and docker run commands. You cannot separately push the docker-compose.yml file to Docker Hub or other registries, and in a typical Compose setup there are references a number of standard images you don't need to push yourself (the standard Docker Hub redis and cassandra images will be fine no matter where you run them).
This means you need to do two things:
Push the application image (but not its public-image dependencies) to a registry; and
Publish the docker-compose.yml file or another way to run the combined application.
You can use docker-compose push, but in a CI environment it's probably a little more straightforward to use docker build and docker push. Mechanically they're not any different.
Make sure your image contains everything that's needed to run your application, up to external dependencies. The ideal is to be able to docker run your application container, with --net, -e, and -p settings to configure it, but without separately providing the application code or a command. In a docker-compose.yml file see if you can run it with only ports:, environment:, and image: (and build:). Prefer a CMD in the Dockerfile to a command: in docker-compose.yml. If you're bind-mounting host code into the container (unlikely for Go and other compiled languages) delete those volumes:.
A typical sequence for deploying things using Compose might look like:
here$ docker build -t me/myapp:20200525 .
here$ docker push me/myapp:20200525
here$ scp docker-compose.yml there:
here$ ssh there
there$ MYAPP_TAG=20200525 docker-compose up -d
Note that the only thing we directly copied to the target system is the docker-compose.yml that specifies how to run the image; we have not copied any application code or other dependencies, since that is all encapsulated in the image.

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

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

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