Use ghcr in Dockerfile in GHA - docker

I would like to use ghcr as cache to store docker image with part which almost do not change in my project (Ubuntu, miniconda and bunch of Python packages) and then use this image in Dockerfile which adds volumes and code of the project to it. Dockerfile is run by Github Actions. How could I reference to ghcr stored image in From statement of Dockerfile?

How could I reference to ghcr stored image in From statement of Dockerfile?
Image references have the registry in front of them, and when not included, will default to Docker Hub. So for a registry like ghcr you want:
FROM ghcr.io/path/to/image:tag

Related

Dockerfile FROM command - Does it always download from Docker Hub?

I just started working with docker this week and came across a 'dockerfile'. I was reading up on what this file does, and the official documentation basically mentions that the FROM keyword is needed to build a "base image". These base images are pulled from Docker hub, or downloaded from there.
Silly question - Are base images always pulled from docker hub?
If so and if I understand correctly I am assuming that running the dockerfile to create an image is not done very often (only when needing to create an image) and once the image is created then the image is whats run all the time?
So the dockerfile then can be migrated to which ever enviroment and things can be set up all over again quickly?
Pardon the silly question I am just trying to understand the over all flow and how dockerfile fits into things.
If the local (on your host) Docker daemon (already) has a copy of the container image (i.e. it's been docker pull'd) specified by FROM in a Dockerfile then it's cached and won't be repulled.
Container images include a tag (be wary of ever using latest) and the image name e.g. foo combined with the tag (which defaults to latest if not specified) is the full name of the image that's checked i.e. if you have foo:v0.0.1 locally and FROM:v0.0.1 then the local copy is used but FROM foo:v0.0.2 will pull foo:v0.0.2.
There's an implicit docker.io prefix i.e. docker.io/foo:v0.0.1 that references the Docker registry that's being used.
You could repeatedly docker build container images on the machines where the container is run but this is inefficient and the more common mechanism is that, once a container image is built, it is pushed to a registry (e.g. DockerHub) and then pulled from there by whatever machines need it.
There are many container registries: DockerHub, Google Artifact Registry, Quay etc.
There are tools other than docker that can be used to interact with containers e.g. (Red Hat's) Podman.

How to indicate a private registry not using the Dockerfile?

I have a Git repo with a simple Dockerfile. First row goes like this:
FROM python:3.7
My company has an internal registry with the base images. Because of this, the DevOps guys want me to change the Dockerfile to:
FROM registry.company.com:5000/python:3.7
I don't want this infrastructure detail baked in my code. URLs may change, I may want to build this image in another environment, etc. If possible, I would rather indicate the server in the pipeline, but the documentation regarding docker build has no parameter for this.
Is there a way to avoid editing the Dockerfile in this situation?
You would use a build arg for this:
ARG registry=docker.io/library
FROM ${registry}/python:3.7
Then for the build process:
docker build --build-arg registry=registry.company.com:5000 ...
Use docker.io for the registry name for the default Docker Hub, and library is the repository for official docker images, both of which you normally don't see when using the short format. Note that I usually include the library part in the local mirror so that official docker images and other repos that are mirrored can all use the same registry variable:
ARG registry=docker.io
FROM ${registry}/library/python:3.7
That means your local registry would need to have registry.company.com:5000/library/python:3.7.
To force users to specify the registry as part of the build, then don't provide a default value to the arg (or you could default the value of registry to something internal if that's preferred):
ARG registry
FROM ${registry}/python:3.7
You can work around the situation by manually pulling and re-tagging the image. docker build (and docker run) won't try to pull an image that already appears to be present locally, but that also means there's no verification that it actually matches what Docker Hub has. That means you can pull the image from your mirror, then docker tag it to look like a Docker Hub image:
docker pull registry.company.com:5000/python:3.7
docker tag registry.company.com:5000/python:3.7 python:3.7

Shared volume during build?

I have a docker-compose environment setup like so:
Oracle
Filesystem
App
...
etc...
The filesystem container downloads the latest code from our repo and exposes its volume for other containers to mount. This works great except that containers that need to use the code to do builds can't access it since the volume isn't mounted until the containers are run.
I'd like to avoid checkout/downloading the code since the codebase is over 3 gig right now... Hence trying to do something spiffier.
Is there a better way to do this?
As you mentioned, Docker volumes won't work as volumes are used when the container start.
The best solution for your situation is to use Docker multistage Builds. The idea here is to have an image which has the code base and other images can access this code directly from this image.
You basically have an image, that is responsible for pulling the code:
FROM alpine/git
RUN git clone ...
You then build this image, either separately or as the first image in a compose file.
Other images can then use this image as such:
FROM code-image as code
COPY --from=code /git/<code-repository> /code
This will make the code available to all the images, and it will only be pulled once from the remote repo.

Docker: does pulling an image from DockerHub download a Dockerfile to localhost?

I would like to be able to pull a docker image from dockerhub and edit the dockerfile.. I am wondering if dockerhub actually downloads the dockerfile to the localhost and to where it is stored (I am running it from a MAC).
You dont download the docker image and edit their Dockerfile. The Dockerfile is an instruction set on how to build an image. Once the image is made, theres no going backwards. However if its on Dockerhub there should be a link to the Dockerfile. Look around at the page for links to the Dockerfile. Probably just a link to Github.
Once you have the dockerfile you then build it. For instance if you have a terminal open in the same folder as a Dockerimage file you could run
docker build -t myimage .
where myimage is the tag of your image. You will then have an instance of myimage on your local machine.
Also you can make a docker file that extends theres using FROM. For instance your docker file might start with
FROM java:6b38-jdk
# append to their image.
An image does not include a complete Dockerfile. When pulling an image you get an image manifest along with the required file system layers.
You can see some of the build steps with docker history --no-trunc IMAGE but it's not the complete Dockerfile.
There are utilities that try and generate a Dockerfile from the image history

What are the different ways of implementing Docker FROM?

Inheritance of an image is normally done using docker's from command, for example.
from centos7:centos7
In my case, I have a Dockerfile which I want to use as a base image builder, and I have two sub dockerfiles which customize that file.
I do not want to commit the original dockerfile as a container to dockerhub, so for example, I would like to do:
Dockerfile
slave/Dockerfile
master/Dockerfile
Where slave/Dockerfile looks something like this:
from ../Dockerfile
Is this (or anything similar) possible ? Or do I have to actually convert the top level Dockerfile to a container, and commit it as a dockerhub image, before I can leverage it using the docker FROM directive.
You don't have to push your images to dockerhub to be able to use them as base images. But you need to build them locally so that they are stored in your local docker repository. You can not use an image as a base image based on a relative path such as ../Dockerfile- you must base your own images on other image files that exists in your local repository.
Let's say that your base image uses the following (in the Dockerfile):
FROM centos7:centos7
// More stuff...
And when you build it you use the following:
docker build -t my/base .
What happens here is that the image centos7:centos7 is downloaded from dockerhub. Then your image my/base is built and stored (without versioning) in your local repository. You can also provide versioning to your docker container by simply providing version information like this:
docker build -t my/base:2.0 .
When an image has been built as in the example above it can then be used as a FROM-image to build other sub-images, at least on the same machine (the same local repository). So, in your sub-image you can use the following:
FROM my/base
Basically you don't have to push anything anywhere. All images lives locally on your machine. However, if you attempt to build your sub-image without a previously built base image you get an error.
For more information about building and tagging, check out the docs:
docker build
docker tag
create your own image

Resources