django-DefectDojo icon indicating copy to clipboard operation
django-DefectDojo copied to clipboard

support multi-arch docker images and update base to debian bullseye

Open tiagoposse opened this issue 2 years ago • 38 comments

This PR accomplishes two things:

  1. Adapts the github workflows, so that both a multi-arch image is build, for both arm64 and amd64
  2. Updates the base images of defectdojo-django and defectdojo-nginx docker images from debian buster to bullseye

For 1, an additional github action is added, to provide QEMU, which is used to provide emulated environments for building on architecture other than the host arch. Additionally, platforms need to be specified.

Closes #5525

tiagoposse avatar Nov 30 '21 06:11 tiagoposse

Locally, two things to mention:

  • When building the django image, the pyNacl wheel takes 50m to build in my machine. This can be circumvented by installing libsodium previously to running the wheels for requirements.txt (https://github.com/pyca/pynacl/issues/654). I have the idea this won't happen just locally, but the solution is trivial and works for both amd and arm.
  • When building the nginx image, we suffer from a known issue (https://githubmemory.com/repo/laravel/sail/issues/159) when executing curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -. This can by solved by: a) moving this link to http, which is not good; b) using debian bullseye instead of buster

tiagoposse avatar Nov 30 '21 07:11 tiagoposse

Thanks @tiagoposse for the PR and suggestions, will take a look. What do about think about the fact that we build and push arm64 images without testing them? I haven't looked, but it's probably hard to deploy/test arm64 with GitHub Actions? Or maybe it isn't: https://github.com/uraimo/run-on-arch-action?

valentijnscholten avatar Nov 30 '21 08:11 valentijnscholten

IMO arm64 has come a long way and with the m1s, this will become better and better, So I don't think pushing without testing is that bad. Additionally, considering the actual state of the dockerfiles, there is no http/ftp/etc download of binaries, so if everything builds, it should work.

tiagoposse avatar Nov 30 '21 08:11 tiagoposse

Did you test the workflow in your fork, for example by pushing to your personal docker hub account?

valentijnscholten avatar Dec 01 '21 19:12 valentijnscholten

I did not test the github workflows, but I am running these images in my company's cluster, under arm64, and so far have experienced no issues. I've uploaded scan reports successfully defectdojo

tiagoposse avatar Dec 02 '21 11:12 tiagoposse

It's more about if they build well and upload well from GHA. To prevent any errors during our release process.

valentijnscholten avatar Dec 02 '21 11:12 valentijnscholten

I was able to complete the build for django but not for nginx as I faced the error described above. What would be your preferred solution: a) use http://dl.yarnpkg.com/debian/pubkey.gpg instead of https b) try with a python image that is based on debian bullseye, instead of buster

tiagoposse avatar Dec 02 '21 14:12 tiagoposse

We can upgrade to bullseye in 2.6.0, first we want to release 2.5.0 on December 7th.

valentijnscholten avatar Dec 02 '21 15:12 valentijnscholten

@tiagoposse I upgraded to bullseye, but the uwsgi wheel won't build. Do you have any idea? https://github.com/DefectDojo/django-DefectDojo/runs/4718480444?check_suite_focus=true#step:4:1674

valentijnscholten avatar Jan 05 '22 18:01 valentijnscholten

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Jan 26 '22 17:01 github-actions[bot]

Conflicts have been resolved. A maintainer will review the pull request shortly.

github-actions[bot] avatar Jan 26 '22 18:01 github-actions[bot]

sorry for the delay on this, lots of personal things to take care this month. It seems that uwsgi needs gcc to be built on bullseye. Since this is being built on a stage, I guess this wouldn't pose issues?

tiagoposse avatar Jan 26 '22 18:01 tiagoposse

uwsgi won't build on bullseye if you use pip wheel uwsgi as you can see in the PR that I linked.

valentijnscholten avatar Jan 26 '22 18:01 valentijnscholten

I understand that :) it is possible to build it by installing gcc, here's me installing it on the image in your pr:

tiagoposse@admins-MBP django-DefectDojo % docker run -ti --entrypoint bash --rm python:3.8.12-slim-bullseye@sha256:3d3edc52cfae3ed6fb8303559f10184f962a8069194b2dee93baaac66ebedeb5
root@20aeba31192f:/# pip wheel uwsgi
Collecting uwsgi
  Downloading uwsgi-2.0.20.tar.gz (804 kB)
     |████████████████████████████████| 804 kB 5.7 MB/s
Building wheels for collected packages: uwsgi
  Building wheel for uwsgi (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /usr/local/bin/python -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/setup.py'"'"'; __file__='"'"'/tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-712uy3z8
       cwd: /tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/
  Complete output (42 lines):
  /usr/local/lib/python3.8/distutils/dist.py:274: UserWarning: Unknown distribution option: 'descriptions'
    warnings.warn(msg)
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib
  copying uwsgidecorators.py -> build/lib
  installing to build/bdist.linux-x86_64/wheel
  running install
  using profile: buildconf/default.ini
  detected include path: ['/usr/include', '/usr/local/include']
  Traceback (most recent call last):
    File "/tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/uwsgiconfig.py", line 750, in __init__
      gcc_version_components = gcc_version.split('.')
  AttributeError: 'NoneType' object has no attribute 'split'

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/setup.py", line 117, in <module>
      setup(
    File "/usr/local/lib/python3.8/site-packages/setuptools/__init__.py", line 153, in setup
      return distutils.core.setup(**attrs)
    File "/usr/local/lib/python3.8/distutils/core.py", line 148, in setup
      dist.run_commands()
    File "/usr/local/lib/python3.8/distutils/dist.py", line 966, in run_commands
      self.run_command(cmd)
    File "/usr/local/lib/python3.8/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/usr/local/lib/python3.8/site-packages/wheel/bdist_wheel.py", line 335, in run
      self.run_command('install')
    File "/usr/local/lib/python3.8/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/usr/local/lib/python3.8/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/setup.py", line 77, in run
      conf = uc.uConf(get_profile())
    File "/tmp/pip-wheel-igq1clph/uwsgi_6c5650649c1a4edeaf0724b5b7fa5d24/uwsgiconfig.py", line 758, in __init__
      raise Exception("you need a C compiler to build uWSGI")
  Exception: you need a C compiler to build uWSGI
  ----------------------------------------
  ERROR: Failed building wheel for uwsgi
  Running setup.py clean for uwsgi
Failed to build uwsgi
ERROR: Failed to build one or more wheels
WARNING: You are using pip version 21.2.4; however, version 21.3.1 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
root@20aeba31192f:/# apt update > /dev/null && apt install -y gcc > /dev/null

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.


WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

debconf: delaying package configuration, since apt-utils is not installed
root@20aeba31192f:/# pip wheel uwsgi
Collecting uwsgi
  Using cached uwsgi-2.0.20.tar.gz (804 kB)
Building wheels for collected packages: uwsgi
  Building wheel for uwsgi (setup.py) ... done
  Created wheel for uwsgi: filename=uWSGI-2.0.20-cp38-cp38-linux_x86_64.whl size=510247 sha256=378226b3d7ed028d25cfaa590d7007a559edcc4567caa88e40a1221bd6e996e3
  Stored in directory: /root/.cache/pip/wheels/cb/4d/54/002a215100a8c4e125654600f0a4304dae742442ddc4ba6ea1
Successfully built uwsgi

You'll notice it fails without gcc, but succeeds with. I am able to build the django image successfully by adding gcc to the "build" stage (first line of apt install):

FROM base as build
WORKDIR /app
RUN \
  apt-get -y update && \
  apt-get -y install --no-install-recommends \
    gcc \
    build-essential \
    dnsutils \
    default-mysql-client \
    libmariadb-dev-compat \
    postgresql-client \
    xmlsec1 \
    git \
    uuid-runtime \
    && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists && \
  true

Since this is not the final stage of the image, the final image is not bloated by the change.

I was able to build both defecdojo-django and defectdojo-nginx locally for both platforms after adding gcc to the respective apt install steps. I can provide an MR to your branch if needed.

I can also confirm that both issues specified in my post above no longer happen after updating to bullseye:

Locally, two things to mention:

  • When building the django image, the pyNacl wheel takes 50m to build in my machine. This can be circumvented by installing libsodium previously to running the wheels for requirements.txt (Pynacl on Apple Silicon/ARM64 pyca/pynacl#654). I have the idea this won't happen just locally, but the solution is trivial and works for both amd and arm.
  • When building the nginx image, we suffer from a known issue (https://githubmemory.com/repo/laravel/sail/issues/159) when executing curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -. This can by solved by: a) moving this link to http, which is not good; b) using debian bullseye instead of buster

I would also be able to push these updates to this MR if you'd prefer. The working branch is https://github.com/tiagoposse/django-DefectDojo/tree/update_to_bullseye

tiagoposse avatar Jan 27 '22 07:01 tiagoposse

hmm I thought I had gcc installed as part of build-essentials. I followed the steps from https://uwsgi-docs.readthedocs.io/en/latest/Install.html. The result was that I could run pip install uwsgi which worked fine. But pip wheel uwsgi didn't work. Also I didn't get any clear error message like the one you have, I am just seeing "command exited with code 1". Nothing else. I will do another test on my branch.

valentijnscholten avatar Jan 27 '22 08:01 valentijnscholten

OK, seems to work now with gcc, didn't think of that as pip install also seemed to compile the wheel. Can you add all your changes to the PR so we can review? Can you rebase against the dev branch?

valentijnscholten avatar Jan 27 '22 08:01 valentijnscholten

FYI Build still fails, even with gcc added: https://github.com/DefectDojo/django-DefectDojo/runs/4963310430?check_suite_focus=true

valentijnscholten avatar Jan 27 '22 08:01 valentijnscholten

I'm seeing the same behaviour now. Works locally but fails on github actions

tiagoposse avatar Jan 27 '22 08:01 tiagoposse

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Jan 27 '22 08:01 github-actions[bot]

Rebasing to dev added a few conflicts

tiagoposse avatar Jan 27 '22 08:01 tiagoposse

Conflicts have been resolved. A maintainer will review the pull request shortly.

github-actions[bot] avatar Jan 27 '22 08:01 github-actions[bot]

Locally it's a hit and miss, I can build several successfully several times in a row and then hit errors another several times in a row. It seems though that I've finally worked around it. I found this post and comment: https://github.com/unbit/uwsgi/issues/1318#issuecomment-429464275, which puts CPUCOUNT=1 before the wheel installation. this seems to fix it and a successful run can be seen here: https://github.com/tiagoposse/django-DefectDojo/runs/4964232859?check_suite_focus=true

tiagoposse avatar Jan 27 '22 09:01 tiagoposse

still fails at https://github.com/DefectDojo/django-DefectDojo/runs/4964457401?check_suite_focus=true

valentijnscholten avatar Jan 27 '22 10:01 valentijnscholten

The build you linked fails for defectdojo-nginx, for which you didn't add CPUCOUNT=1 (nginx image also builds the wheel so it also needs this) I've cleaned up this MR as well after all the trash that got mixed in the rebase.

tiagoposse avatar Jan 27 '22 12:01 tiagoposse

ah thanks, doing too many things at the same time. Can you add the comments from my PR to your PR? If all gets green, we'll merge yours for 2.8.0.

valentijnscholten avatar Jan 27 '22 13:01 valentijnscholten

totally understandable. Comments added, fingers crossed :D

tiagoposse avatar Jan 27 '22 13:01 tiagoposse

Thanks for working with us on this. Could you update the description a little bit to reflect what the PR does/changes?

valentijnscholten avatar Jan 27 '22 17:01 valentijnscholten

my pleasure. Done

tiagoposse avatar Jan 27 '22 18:01 tiagoposse

I've finally managed to get around testing the deployment of this version in arm64 today and it didn't work. The pinned SHA digest seems to be for amd64 only. I'll provide a fix shortly.

tiagoposse avatar Jan 28 '22 10:01 tiagoposse

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Feb 01 '22 19:02 github-actions[bot]