Git repo in Docker image not picking up changes on fresh build - docker

My Git repo isn't changing in my Docker image even when rebuilding with a new tag.
I run git clone in a build and it works:
# dockerfile
FROM python:3.8
ENV PYTHONUNBUFFERED 1
# To fix GPG key error when running apt-get update
RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/3bf863cc.pub
RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/7fa2af80.pub
RUN apt-get update && apt-get install -y git
RUN git clone https://github.com/my_git_username/repo_name.git
WORKDIR /repo_name
I build:
docker build -t username/exam:0.1
Then, I push a file named tmp.txt to that repo, and run a new build:
docker build -t username/exam:0.2
I expect that this command fails, because I changed the repo to private, but it succeeds. So I went inside the container and checked the contents:
docker run -it username/exam:0.2
import os
print(os.listdir(os.getcwd()))
And I confirm that tmp.txt does not exist (which is the previous state of the repo).
This is what I would expect:
=> ERROR [6/7] RUN git clone https://github.com/my_git_username/repo_name.git 1.1s
------
> > [6/7] RUN git clone https://github.com/my_git_username/repo_name.git:
> #10 0.632 Cloning into 'repo_name'...
> #10 1.007 fatal: could not read Username for 'https://github.com': No such device or address
> ------
> executor failed running [/bin/sh -c git clone https://github.com/my_git_username/repo_name.git]: exit code: 128
What I need help with:
Why is the git repo at the previous commit in the second image?
How can I automatically bring the latest modifications without modifying the Dockerfile?

Use docker build --no-cache. Docker caches layers, and is likely caching the git clone layer (step), because the command hasn't changed and the checksums of the previous layers haven't changed.
Example: docker build --no-cache -t username/exam:0.3 ..

Related

Using pip install from private gitlab repository, when building Docker image

I am trying to build a docker image on an Ubuntu machine, where one of the dependencies is
an internally hosted Gitlab project (IT IS NOT HOSTED ON GITLAB.COM).
The docker file is:
FROM rayproject/ray:1.12.0-py39-cpu
RUN git config --global user.name <MY USER NAME>
RUN git config --global http.sslVerify false
COPY .ssh/id_rsa /home/ray/.ssh/id_rsa
RUN sudo chmod -R 777 ~/.ssh/*
RUN eval "$(ssh-agent -s)"
RUN eval `ssh-agent -s` && ssh-add $HOME/.ssh/id_rsa
RUN pip install git+https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git
I am attempting to build the docker file with:
docker build .
I receive this error message when building the docker image:
Step 8/29 : RUN pip install git+https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git
---> Running in b9e11319c84d
Collecting git+https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git
Cloning https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git to /tmp/pip-req-build-l1qklujg
Running command git clone -q https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git /tmp/pip-req-build-l1qklujg
fatal: could not read Username for 'https://gitlab.<EMPLOYERS DOMAIN>.com': No such device or address
WARNING: Discarding git+https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git. Command errored out with exit status 128: git clone -q https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git /tmp/pip-req-build-l1qklujg Check the logs for full command output.
ERROR: Command errored out with exit status 128: git clone -q https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git /tmp/pip-req-build-l1qklujg Check the logs for full command output.
However, from my machine, I can run
pip install https://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git
without being asked to enter my username/password.
I'm unsure whether or not my machine was configured to use the RSA key to login into the internal Gitlab.
How can I install the package when building the docker image?
Use ssh instead of https. i.e.
RUN pip install git+ssh://gitlab.<EMPLOYERS DOMAIN>.com/xyz/my_project.git
Just to recall a security issue that wouldn't fit in a mere comment:
Every datum that we COPY within the Dockerfile is kept forever
(even if we do RUN rm -fr something afterwards!),
so this means here that anyone that can pull the Docker image can retrieve the contents of the /home/ray/.ssh/id_rsa fileā€¦ to avoid this, two ways:
either do the cloning of the repo outside of the Dockerfile from GitLab-CI (then do a mere COPY my_project my_project then RUN pip install ./my_project)
or use the docker build --ssh feature.

Unable to Successfully Build Go-Based Docker Image

When attempting to build a GoLang-based Docker Image, the Docker executor runs into the following error:
. . .go: $GIT_REPO#v1.9.11: reading $GIT_REPO/go.mod at revision v0.0.07: unknown revision v0.0.07
at the following RUN instruction from the Dockerfile used:
RUN go build . . .
where GIT_REPO represents the private repo. full path, including owner and name.
The Docker executor encounters this error with go1.13.x and higher; the Docker executor does not encounter this error with go1.12.x.
The vendor dir. contains all required packages. Tags are confirmed to be present.
Proper SSH keys were even added to the private Go common repo. with successful
git clone . . .
commands outside of building Docker images, but still encountering the same error above.
EDIT:
Verify your remote repo in bitbucket.org actually has the v0.0.7 tag you're trying to build against.
While a local build may work if the git tag exists locally - a docker build will pull from the remote source and fail with an error like go.mod at revision v0.0.7: unknown revision v0.0.7 - if the tag does not exist remotely.
To push your local tags to the remote repo:
git push --tags
For more granular tag operations see.
Docker builds by default can only access public repos. Since you need access to a private repo, you need to include a read-ssh key to the Docker build process (keys should never be checked into the repo!).
It is critically important, however, you do this in a multi-stage build, so you do not include your SSH keys in the final image.
This blog post walks through all the steps. But to include a working example:
To build the docker image:
SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" \
docker build -t "myapp:v0.0.1" --build-arg SSH_PRIVATE_KEY .
And the Dockerfile using a bitbucket.org private repo site:
FROM golang:1.14.6 AS build
WORKDIR /bld
COPY *.go go.mod go.sum ./
ARG SSH_PRIVATE_KEY
# ***NEVER*** DO THIS IN A SINGLE-STAGE DOCKER BUILD (see below)
RUN \
mkdir -p ~/.ssh && \
umask 0077 && \
echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa && \
git config --global url."git#bitbucket.org:".insteadOf https://bitbucket.org/ && \
ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts
RUN \
go get && \
CGO_ENABLED=0 go build -o app
# final stage of multi-stage: will appropriately *NOT* include SSH keys
FROM scratch
COPY --from=build \
/etc/ssl /etc/ssl
COPY --from=build \
/bld/app /app/myapp
CMD ["/app/myapp"]
There are two problems to solve here:
1. How to allow Docker to access local SSH keys, safely?
2. How to tell Go not to use public registry to fetch private packages?
Short Answers
Since Docker v18.09, there's a built-in solution to handle SSH authentication during the build phase (more). It's also much easier and safer, compared to passing build arguments, and eliminates the need for a multi-stage Docker build.
Go has a GOPRIVATE environment variable to identify private packages. (more)
Long Answer
Step-by-step:
1. Make sure ssh-agent is setup and knows the SSH key
Github has a quick guide on this subject, explaining the process for different operating systems. See Generating a new SSH key and adding it to SSH agent.
2. Enable BuildKit for Docker
Without BuildKit, docker build won't recognize --ssh option.
From the Docker reference:
Easiest way from a fresh install of docker is to set the
DOCKER_BUILDKIT=1 environment variable when invoking the docker build
command, such as:
$ DOCKER_BUILDKIT=1 docker build .
To enable docker BuildKit by
default, set daemon configuration in /etc/docker/daemon.json feature
to true and restart the daemon:
{ "features": { "buildkit": true } }
Docker Desktop users can manage daemon configurations via Preferences > Docker Engine.
4. Update Dockerfile
4.1. Make sure Git uses SSH instead of HTTPs
Go tends to fetch public packages via HTTPs. You can adjust this behavior by updating git configurations:
RUN git config --global url.git#github.com:.insteadOf https://github.com/
You should probably do this on your local machine as well.
4.2. Request SSH access where it's required
Each RUN command the needs SSH access should be mounted with type=ssh. For
Example:
RUN --mount=type=ssh git clone ...
4.3. Make sure Go knows your private packages
Update GOPRIVATE variable:
RUN go env -w GOPRIVATE="github.com/your-org/private-repo"
Putting all of it together, in following sample of a Dockerfile:
FROM golang:1.16.3-alpine3.13
RUN apk update
RUN apk add git openssh
RUN mkdir /app
ADD . /app
WORKDIR /app
# You can replace github.com with any other Git host
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# Make sure git uses SSH to fetch packages, not HTTPs
RUN git config --global url.git#github.com:.insteadOf https://github.com/
# Make Go knows which packages are private.
RUN go env -w GOPRIVATE="github.com/your-org/private-repo"
# GOPRIVATE is a comma separated list glob-patterns.
# You can use a wildcard to match every repo in an organization:
# e.g.: GOPRIVATE="github.com/your-org/*"
# Mount the build command with type `ssh`.
RUN --mount=type=ssh go get && go build -o main .
CMD ["/app/main"]
6. Build the image with --ssh option:
Having BuildKit enabled by default:
$ docker build --ssh default -t my-app:latest .

How to setup GitLab CE CI to user docker images for runners

I've now tried for several days to get a runner working on a docker container. I have a Debian running system with GitLab, gitlab-runner and docker installed. I want to use docker as a container for my runners, because shell executors are installing all things on my CI maschine...
What I have done until now: I installed docker like it is described in the GitLab CE docs and run this command:
gitlab-runner register -n \
--url DOMAIN \
--registration-token TOKEN \
--executor docker \
--description "docker-builder" \
--docker-image "gliderlabs/alpine" \
--docker-privileged
then I created a test repo to look if it is working, with this .gitlab-ci-yml
variables:
# GIT_STRATEGY: fetch # re-uses the project workspace
GIT_CHECKOUT: "false" # don't checkout the working copy to a revision related to the CI pipeline
GIT_DEPTH: "3"
cache:
paths:
- node_modules/
stages:
- deploy
before_script:
- apt-get update
- apt-get install -y -qq sshpass
- ls -la
# ======================= Jobs=======================
# Teporaly disable jobs by adding a . (dot) before the job name
ftp-upload:
stage: deploy
# environment: Production
except:
- testing
script:
- rm ./package-lock.json
- npm install
- ls -la
- sshpass -V
- export SSHPASS=$PASSWORD
- sshpass -e scp -o stricthostkeychecking=no -r . $USERNAME#$HOST:/Test
only:
- master
# ===================== ./Jobs ======================
but I get an error in the GitLab CI console:
Running with gitlab-runner 11.1.0 (081978aa)
on docker-builder 5ce3c211
Using Docker executor with image gliderlabs/alpine ...
Pulling docker image gliderlabs/alpine ...
Using docker image sha256:74a78e860d7b39aa694197a70d4467019b611b80c21d886fcd1bfc04d2e767d4 for gliderlabs/alpine ...
Running on runner-5ce3c211-project-3-concurrent-0 via srvvgit001...
Cloning repository for master with git depth set to 3...
Cloning into '/builds/additive/test'...
Skipping Git checkout
Skipping Git submodules setup
Checking cache for default...
Successfully extracted cache
/bin/sh: eval: line 64: apt-get: not found
$ apt-get update
ERROR: Job failed: exit code 127
I don't know much about those docker containers but them seems good for reuse without modifying my CI system. It looks here that it is installing another alpine image/container, but have I not said GitLab runner to use an existing one?
Hopefully, there is someone that can easier explain to me how this works... I really have tried anything google gave me.
The Docker image you are using is a Alpine image, which is a minimal Linux distribution.
Alpine Linux is not using apt for package management but apk.
The problem is in your .gitlab-ci-yml's before_script section where you are trying to run apt.
To solve your issue, replace the use of apt by apk:
before_script:
- apk update
- apk add sshpass
...
Read more about the Alpine Linux package management here.

How to run `git clone` in docker file?

I have specified a git clone command in the docker file as below.
RUN git clone https://github.com/zhaoyi0113/test.git
but I got this error when build the docker image:
Cloning into 'test'...
fatal: could not read Username for 'https://github.com': No such device or address
I wonder why it doesn't work. I am able to run this command on my host. Is there anything different if I list it on docker file?
You can pass credentials as arguments to container. This should work
FROM alpine:3.8
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
ARG username
ARG password
RUN git clone https://${username}:${password}#github.com/username/repository.git
ENTRYPOINT ["sleep 10"]
but it might be unsafe if you want to distribute that image
then build
docker build \
--no-cache \
-t git-app:latest \
--build-arg username=user \
--build-arg password=qwerty \
.
I know what wrong with this problem. The issue is because the repo I am cloning is a private repo which means it requires credential to connect to github. Fixing it by passing credentials to the container.

Gitlab.com runners: How do I install and run software from an external repos?

I'm pretty new to Gitlab.com's CI and to docker.
I have a simple python pelican static blog that builds with a simple .gitlab-ci.yml
image: python:2.7-alpine
pages:
script:
- pip install -r requirements.txt
- pelican -s publishconf.py
artifacts:
paths:
- public
So I see that it specifies a python docker image, uses pip to install various python scripts, then runs pelican all within that image.
Now my issue is that I want to run a my own version of pelican. I modified my requirements.txt file to look for my own branch of pelican, but this fails
beautifulsoup4
markdown
smartypants
typogrify
git+https://github.com/jerryasher/pelican.git#hidden-cats
pelican-fontawesome
pelican-gist
pelican-jsfiddle
pelican-neighbors
Now when it builds, Gitlab's Runner tells me:
Running with gitlab-ci-multi-runner 1.9.0 (82714ae)
Using Docker executor with image python:2.7-alpine ...
Pulling docker image python:2.7-alpine ...
Running on runner-e11ae361-project-1654117-concurrent-0 via runner-e11ae361-machine-1484613050-ce975c76-digital-ocean-4gb...
Cloning repository...
Cloning into '/builds/jerrya/ashercodes'...
Checking out 532f8b38 as master...
$ pip install -r requirements.txt
Collecting git+https://github.com/jerryasher/pelican.git#hidden-cats (from -r requirements.txt (line 5))
Cloning https://github.com/jerryasher/pelican.git (to hidden-cats) to /tmp/pip-72xxqt-build
Error [Errno 2] No such file or directory while executing command git clone -q https://github.com/jerryasher/pelican.git /tmp/pip-72xxqt-build
Cannot find command 'git'
ERROR: Build failed: exit code 1
Okay,
Git doesn't seem to be present. Indeed prior to the above attempt, I had added a line (that failed) to the .gitlab-ci.yml script saying to use git to clone that repo locally, and that also failed, because ... no git.
(The docker image I am using python:2.7-alpine also seems to have no apt-get.)
Do I need to build my own docker image containing git and python and anything else that I require, or is there some "usual" way to have a Gitlab.com runner pull in an external program from either a git repo, or some typical linux package repository?
And if I can't do this, is that in this case the fault of the runner, or the fault of the docker image?
You can just install git (and any other package) if you need it. Your own image will be faster but it's not needed.
pages:
script:
- apk --update add git openssh
- pip install -r requirements.txt
...

Resources