Flutter in Docker container fails in Jenkins but not locally - docker

I'm trying to get one of our very simple flutter apps to run its test suite in Jenkins.
I have the following Dockerfile:
FROM ubuntu:bionic
ARG WORKING_DIR=${HOME}
ARG FLUTTER_ARCHIVE=flutter_linux_v0.5.1-beta.tar.xz
COPY ${FLUTTER_ARCHIVE} ${WORKING_DIR}
RUN apt-get update
RUN apt-get -y install xz-utils
RUN tar -xf "${WORKING_DIR}/${FLUTTER_ARCHIVE}"
ENV PATH="${WORKING_DIR}/flutter/bin:${PATH}"
RUN apt-get -y install git libglu1 lib32stdc++6
RUN rm ${WORKING_DIR}/${FLUTTER_ARCHIVE}
I build the container on my machine, navigate to the source code directory of the flutter app and run the following command:
docker run -td -vpwd:/source flutter:flutter
Where flutter:flutter is my built image.
I navigate into the container using docker exec and execute flutter packages get and then flutter test. Everything works as expected and all tests pass.
However, when I try to use the exact same Dockerfile through Jenkins, I get following error:
/flutter/bin/flutter: line 161: /flutter/bin/cache/dart-sdk/bin/dart: Permission denied
I'm guessing it has something do with users and that differs somehow between how Jenkins runs and how it works when I run the steps manually. The steps in the Jenkinsfile are exactly as what I ran manually above:
stages {
stage('test') {
steps {
script {
sh 'flutter packages get'
sh 'flutter test'
}
}
}
}
And I have pointed to our local registry where the image resides:
agent {
docker "flutter:flutter"
}
I am out of ideas and I don't really know how to solve this error. Any help would be greatly appreciated.
UPDATE
I have tried the following:
Creating a user in the Dockerfile using useradd and then switching to that user using USER <user> Dockerfile syntax and performing all operations as that user.
Creating a user in the Dockerfile using useradd, performing all operations as root but then setting chown user:user -R /flutter to change ownership of Flutter directory
Both of the above required me to add the following to the Jenkinsfile:
agent {
docker {
image 'flutter:flutter'
args '-u user --privileged'
}
}
But still no luck.

Related

Why is this Todo app build failing in Jenkins when deploying on AWS Linux using Docker file in WSL2?

So I was trying to deploy a simple CD pipeline using docker by ssh’ing into my AWS Linux EC2 instance in the WSL2 terminal. The job is failing every time returning the following error:
Started by user Navdeep Singh Running as SYSTEM Building on the
built-in node in workspace /var/lib/jenkins/workspace/todo-dev
[todo-dev] $ /bin/sh -xe /tmp/jenkins6737039323529850559.sh + cd
/home/ubuntu/project/django-todo /tmp/jenkins6737039323529850559.sh:
2: cd: can’t cd to /home/ubuntu/project/django-todo Build step
‘Execute shell’ marked build as failure Finished: FAILURE
DockerFile contents:
FROM python:3 RUN pip install django==3.2
COPY . .
RUN python manage.py migrate
CMD [“python”,“manage.py”,“runserver”,“0.0.0.0:8000”]
Everything goes fine. This error cd: can’t cd to /home/ubuntu/project/django-todo Build step ‘Execute shell’ marked build as failure Finished: FAILURE is not an actual.
Your agent Node is not online.
To fix the problem, find commands on your jenkins web page after an agent setup. You need to run those commands from your terminal. See the screenshot for more details.
Make sure that your jenkins public IP and node agent public IP are the same. If an error occurs, you need to run some commands on the terminal. This is not a real error.
this issue follow this step which i give you
For Agent--->
change your ip here(44.203.138.174:8080) to your EC2 ip
1.curl -sO http://44.203.138.174:8080/jnlpJars/agent.jar
2.java -jar agent.jar -jnlpUrl http://44.203.138.174:8080/manage/computer/todo%2Dagent/jenkins-agent.jnlp -secret beb62de0f81bfd06e4cd81d1b896d85d38f82b87b21ef8baef3389e651c9f72c -workDir "/home/ubuntu"
For JOb --->
sudo vi /etc/sudoers
then add this command below root access in sudoers file
jenkins ALL=(ALL) NOPASSWD: ALL
3.then goto the ubuntu directory using cd .. then run this codes
grep ^ubuntu /etc/group
id jenkins
sudo adduser jenkins ubuntu
grep ^ubuntu /etc/group
4.restart the jenkins relogin
sudo systemctl stop jenkins
then you good to go

Is there a way to run donet sonnarscanner inside docker container in Jenkins?

I am trying to do some SonarCloud code analyses on Jenkins with a donet docker container that is already built by my organization. However, I have to install the sonnarscanner tool on top of it, but I am getting permission denials when running the tool.
This is what I've tried so far:
stage("Pull dotnet image") {
dotnetCoreImage = dockerImage("dotnet2.0")
}
dotnetCoreImage.inside() {
stage("Start sonar scanner") {
sh "dotnet tool install --tool-path /tmp/.donet/tools dotnet-sonarscanner; \
chmod 777 /tmp/.donet/tools/ -R;
export PATH=/tmp/.donet/tools; \
dotnet sonarscanner begin \
/d:sonar.host.url=https://sonarcloud.io \
/v:'1.0' \
/d:sonar.cs.opencover.reportsPaths='src/test/coverage/*.opencover.xml'\
/d:sonar.branch.name=${env.BRANCH_NAME}"
}
But I get the following errors:
16:00:46.527 16:00:46.527 WARNING: Error occurred when installing the loader targets to '/.local/share/Microsoft/MSBuild/4.0/Microsoft.Common.targets/ImportBefore/SonarQube.Integration.ImportBefore.targets'. 'Access to the path '/.local/share/Microsoft/MSBuild/4.0/Microsoft.Common.targets/ImportBefore' is denied.'
So my question is if there is a way to run inside the docker image with more permissions such as root.
(Cannot do sudo since it is not installed in the docker image)

Is there any way to run "pkexec" from a docker container?

I am trying to set up a Docker image (my Dockerfile is available here, sorry for the french README: https://framagit.org/Gwendal/firefox-icedtea-docker) with an old version of Firefox and an old version of Java to run an old Java applet to start a VPN. My image does work and successfully allows me to start the Java applet in Firefox.
Unfortunately, the said applet then tries to run the following command in the container (I've simply removed the --config part from the command as it does not matter here):
INFO: launching '/usr/bin/pkexec sh -c /usr/sbin/openvpn --config ...'
Then the applet exits silently with an error. While investigating, I've tried running a command with pkexec with the same Docker image, and it gives me this result:
$ sudo docker-compose run firefox pkexec /firefox/firefox-sdk/bin/firefox-bin -new-instance
**
ERROR:pkexec.c:719:main: assertion failed: (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0)
But I don't know polkit at all and cannot understand this error.
EDIT: A more minimal way to reproduce the problem is with this Dockerfile:
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y policykit-1
And then run:
$ sudo docker build -t pkexec-test .
$ sudo docker run pkexec-test pkexec echo Hello
Which leads here again to:
ERROR:pkexec.c:719:main: assertion failed: (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0)
Should I conclude that pkexec cannot work in a docker container? Or is there any way to make this command work?
Sidenote: I have no control whatsoever on the Java applet that I try to run, it is a horrible and very dated proprietary black box that I am supposed to use at work, for which I have no access to the source code, and that I must use as is.
I have solved my own problem by replacing pkexec by sudo in the docker image, and by allowing passwordless sudo.
Given an ubuntu docker image where a user called developer was created and configured with a USER statement, add these lines:
# Install sudo and make 'developer' a passwordless sudoer
RUN apt-get install sudo
ADD ./developersudo /etc/sudoers.d/developersudo
# Replacing pkexec by sudo
RUN rm /usr/bin/pkexec
RUN ln -s /usr/bin/sudo /usr/bin/pkexec
with the file developersudo containing:
developer ALL=(ALL) NOPASSWD:ALL
This replaces any call to pkexec made in a process running in the container, by a call to sudo without any password prompt, which works nicely.

Run commands inside Docker container without mounting project directory

My Jenkins pipeline uses the docker-workflow plugin. It builds a Docker image and tags it app. The build step fetches some dependencies and bakes them into the image along with my app.
I want to run two commands inside a container based on that image. The command should be executed in the built environment, with access to the dependencies. I tried using Image.inside, but it seems to fail because inside mounts the project directory over the working directory (?) and so the dependencies aren't available.
docker.image("app").inside {
sh './run prepare-tests'
sh './run tests'
}
I tried using docker.script.withDockerContainer too, but the commands don't seem to run inside the container. The same seems to be true for Image.withRun. At least with that I could specify a command, but it seems that I'd have to run specify both commands in one statement. Also it seems that withRun doesn't fail the build if the command doesn't exit cleanly.
docker
.image("app")
.withRun('', 'bash -c "./app prepare-tests && ./app tests"') { container ->
sh "exit \$(docker wait ${container.id})"
}
Is there a way to use Image.inside without mounting the project directory? Or is there are more elegant way of doing this?
docker DSL, like docker.image().inside() {} etc will mount jenkins job workspace dir to container and make it as the WORKDIR which will overwrite the WORKDIR in Dockerfile.
You can verify that from jenkins console output .
1) CD workdir fristly
docker.image("app").inside {
sh '''
cd <WORKDIR of image specifyed in Dockerfile>
./run prepare-tests
./run tests
'''
}
2) Run container in sh , rather than via docker DSL
sh '''
docker run -i app bash -c "./run prepare-tests && ./run tests"
'''

Using Jekyll docker inside Jenkins

I'm trying to build a jekyll website via my Jenkins server (which runs inside a container) and I have a stage in my Jenkinsfile that looks like this:
stage('Building Website') {
agent {
docker {
image 'jekyll/jekyll:builder'
}
}
steps {
sh 'jekyll --version'
}
}
The very first time I run my job it pulls the jekyll docker image and runs fine (although it does fetch a bunch of gems before running jekyll which doesn't happen when I run the docker manually outside jenkins) but then the next jobs fail giving this error:
jekyll --version
/usr/jekyll/bin/jekyll: exec: line 15: /usr/local/bundle/bin/jekyll: not found
Any ideas what I'm doing wrong here?
As you can see in the jenkins log file, jenkins runs docker with the -u 1000:1000 argument, since this user does not exits in the jekyll/jekyll image, the command fails with the error .../bin/jekyll: not found
Here is a sample Jenkinsfile:
pipeline {
agent
{
docker
{
image 'jekyll/jekyll:3.8'
args '''
-u root:root
-v "${WORKSPACE}:/srv/jekyll"
'''
}
}
stages {
stage('Test') {
steps {
sh '''
cd /srv/jekyll
jekyll --version
'''
}
}
}
}
To add to the other answer, note the containerized Jenkins doesn't not contain the docker binary, so docker commands will still fail.
A few solutions
Make a dockerfile that inherits from the jenkins image and installs docker as well, creating a new image.
Manually install docker inside of the container. This will work until you pull a new image, and you'll have to do it over again.
Open an interactive terminal into the jenkins container
docker container exec -it -u root <container id> bash
Then install docker
curl https://get.docker.com/ > dockerinstall && chmod 777 dockerinstall && ./dockerinstall
Exit the container and set perms on docker.sock
sudo chmod 666 /var/run/docker.sock
Finished!

Resources