Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Build issues in alpine docker due to the latest lxml version bump #192

Open
crisp2u opened this issue Dec 16, 2019 · 17 comments
Open

Build issues in alpine docker due to the latest lxml version bump #192

crisp2u opened this issue Dec 16, 2019 · 17 comments
Assignees
Labels

Comments

@crisp2u
Copy link

crisp2u commented Dec 16, 2019

Hello, the current version 1.0.58 does not work for me inside a docker alpine container. After the latest lxml version bump I can't install using pip anymore due to an issue with libxml2. The error message is:
Could not find function xmlCheckVersion in library libxml2. Is libxml2 installed?
I could not find a solution yet and I tried the obvious apk libxslt-dev libxml2-dev python3-dev

The included image builds fine but I'm running terraform-compliace along side atlantis and I'm using a custom atlantis image for that.

For now I've downgraded to 1.0.57. No deal breaker, but I wanted to report it in case someone else hits this.

@eerkunt
Copy link
Member

eerkunt commented Dec 16, 2019

Thanks a lot!

May I ask the version of the Alpine image please ? Let me try to reproduce the problem.

@crisp2u
Copy link
Author

crisp2u commented Dec 16, 2019

That would be alpine:3.10 from here

@eerkunt
Copy link
Member

eerkunt commented Dec 16, 2019

Thanks! Will have a look today

@eerkunt
Copy link
Member

eerkunt commented Dec 16, 2019

It looks like it involves some compilers when libxml is being installed.

I had to install some other packages, better to do this in a multi-staged Dockerfile since usually it is not required to have compilers on container run-time.

Successfully installed lxml-4.4.2 terraform-compliance-1.0.58
bash-5.0# terraform-compliance -v
terraform-compliance v1.0.58 initiated

1.0.58
bash-5.0# terraform-compliance
terraform-compliance v1.0.58 initiated

usage: terraform-compliance [-h] [--terraform [terraform_file]] --features
                            feature directory --planfile plan_file
                            [--identity [ssh private key]] [--version]
terraform-compliance: error: the following arguments are required: --features/-f, --planfile/-p

The packages I installed was ;

  • libxml2-dev
  • libxslt-dev
  • python3-dev
  • gcc
  • build-base

Will have a deeper look throughout the day.

@crisp2u
Copy link
Author

crisp2u commented Jan 22, 2020

@eerkunt yeah, that fixes it but it's not an option the container size is too big. I'm not sure how to do this with multi-staged build beeing a packaged installed using pip, maybe you can share a sample. Thanks

@eerkunt
Copy link
Member

eerkunt commented Jan 22, 2020

Ah yes, we need to remove those libraries after installed of course.

maybe, we can have a multi-stage docker build while we link all packages statically into one binary (including python) and use scratch image to run.

I will have a look

@hasantayyar
Copy link

Here is my solution to this issue

Multi-stage docker using virtual environment (only the part for installing terraform-compliance)

FROM alpine:3.12 as build

RUN apk add libxml2-dev libxslt-dev python3-dev gcc build-base
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install terraform-compliance

FROM alpine:3.12 as release

COPY --from=build /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

@holypriest
Copy link

Another build issue was introduced 2 days ago at version 1.3.15. The package orjson, now used as a dependency of terraform-compliance, cannot be built on Alpine, at least not directly. I tried to install some libraries to aid the rust compiling, but could not get it to work.

Collecting orjson==3.5.2
  Downloading orjson-3.5.2.tar.gz (740 kB)
     |████████████████████████████████| 740 kB 9.3 MB/s 
  Installing build dependencies ... error
  ERROR: Command errored out with exit status 1:
   command: /opt/venv/bin/python3 /tmp/pip-standalone-pip-shg9r05q/__env_pip__.zip/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-1yxcrk2m/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- maturin==0.10.3
       cwd: None
  Complete output (57 lines):
  Collecting maturin==0.10.3
    Downloading maturin-0.10.3.tar.gz (101 kB)
    Installing build dependencies: started
    Installing build dependencies: finished with status 'done'
    Getting requirements to build wheel: started
    Getting requirements to build wheel: finished with status 'done'
      Preparing wheel metadata: started
      Preparing wheel metadata: finished with status 'done'
  Collecting toml~=0.10.0
    Using cached toml-0.10.2-py2.py3-none-any.whl (16 kB)
  Building wheels for collected packages: maturin
    Building wheel for maturin (PEP 517): started
    Building wheel for maturin (PEP 517): finished with status 'error'
    ERROR: Command errored out with exit status 1:
     command: /opt/venv/bin/python3 /tmp/tmp0exq8_1c build_wheel /tmp/tmp2likqe22
         cwd: /tmp/pip-install-cjdykdtv/maturin_9ae8ec26ec534a568f76e8c047e101f0
    Complete output (36 lines):
    running bdist_wheel
    running build
    installing to build/bdist.linux-x86_64/wheel
    running install
    Traceback (most recent call last):
      File "/tmp/tmp0exq8_1c", line 280, in <module>
        main()
      File "/tmp/tmp0exq8_1c", line 263, in main
        json_out['return_val'] = hook(**hook_input['kwargs'])
      File "/tmp/tmp0exq8_1c", line 204, in build_wheel
        return _build_backend().build_wheel(wheel_directory, config_settings,
      File "/tmp/pip-build-env-33h0xq6e/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 216, in build_wheel
        return self._build_with_temp_dir(['bdist_wheel'], '.whl',
      File "/tmp/pip-build-env-33h0xq6e/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 202, in _build_with_temp_dir
        self.run_setup()
      File "/tmp/pip-build-env-33h0xq6e/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 145, in run_setup
        exec(compile(code, __file__, 'exec'), locals())
      File "setup.py", line 96, in <module>
        setup(
      File "/tmp/pip-build-env-33h0xq6e/overlay/lib/python3.8/site-packages/setuptools/__init__.py", line 153, in setup
        return distutils.core.setup(**attrs)
      File "/usr/lib/python3.8/distutils/core.py", line 148, in setup
        dist.run_commands()
      File "/usr/lib/python3.8/distutils/dist.py", line 966, in run_commands
        self.run_command(cmd)
      File "/usr/lib/python3.8/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/tmp/pip-build-env-33h0xq6e/overlay/lib/python3.8/site-packages/wheel/bdist_wheel.py", line 335, in run
        self.run_command('install')
      File "/usr/lib/python3.8/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/usr/lib/python3.8/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "setup.py", line 58, in run
        raise RuntimeError(
    RuntimeError: cargo not found in PATH. Please install rust (https://www.rust-lang.org/tools/install) and try again
    ----------------------------------------
    ERROR: Failed building wheel for maturin
  Failed to build maturin
  ERROR: Could not build wheels for maturin which use PEP 517 and cannot be installed directly
  ----------------------------------------
WARNING: Discarding https://files.pythonhosted.org/packages/50/3d/31803e13b4ddd271047b6a62366bd4abd2cb08dc55a0b47a8b3b2dc2dbc7/orjson-3.5.2.tar.gz#sha256=f385253a6ddac37ea422ec2c0d35772b4f5bf0dc0803ce44543bf7e530423ef8 (from https://pypi.org/simple/orjson/) (requires-python:>=3.6). Command errored out with exit status 1: /opt/venv/bin/python3 /tmp/pip-standalone-pip-shg9r05q/__env_pip__.zip/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-1yxcrk2m/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- maturin==0.10.3 Check the logs for full command output.

@eerkunt
Copy link
Member

eerkunt commented May 17, 2021

Hi @holypriest,

Thanks for testing this out. This is going to be a problem, since orjson becomes a core library for all JSON marshalling/unmarshalling operations. The need of rust for this is crazy, but it sounds like this is how orjson is handled.

We might approach on this is to create one single binary (which is practically a compressed zip file that will unpack on the first run) - which IMHO is going to be problematic on any container due to cold-start issues.

On the other hand, IMHO, using alpine with python stuff may not be the right choice. https://pythonspeed.com/articles/alpine-docker-python/ , alpine is also known as infamous security problems as well. Of course, this is a personal opinion, not trying to force you to not to use alpine.

I will have a look, but since alpine docker images does not accept wheel packages, there may not be hope, or the solution itself might require installing tons of unrelated stuff for just installing one python library.

@eerkunt
Copy link
Member

eerkunt commented May 17, 2021

Sounds like we are not the only ones having this problem: ijl/orjson#8

@holypriest
Copy link

Hello, @eerkunt . Thank you for the feedback!

I think you're right. I went further looking for a solution, but I noticed that there was no reason to keep insisting in the Alpine image due to all the side libraries I had to install (glibc and rust stuff). Even if I get to a solution, the final size of the container would not justify its use.

For now I decided to keep the previous version (1.3.14), but I will test the other tools I need in a Debian container and migrate everything to Debian eventually.

@timgates42
Copy link
Contributor

@eerkunt I'm wondering if you would consider orjson being an optional extra_requirement so it could be used by those wanting the faster parsing and avoided by those who would prefer a lighter dependency set - #516 ?

@eerkunt
Copy link
Member

eerkunt commented Jul 1, 2021

Hi, let me answer on here.

Without orjson or any other high-speed json parser, on some cases terraform-compliance will run in minutes instead of seconds. That is a problem, especially when you run in a pipeline and when your compliance rules grow along with terraform plan.

Can we do it optional ? I am not really sure, since in python packaging we set the required packages upfront and those are installed via pip or something similar via PyPI. Hence, because the problem related with alpine linux is on build-time, making it optional may not be an option really. :(

I will have a look for other high-speed json parsers which might be compatible with Alpine, but IMHO, the main problem is not orjson here, its Alpine linux since it is not using glibc but musl and it disables Python wheels which are only compatible with glibc.

@eerkunt
Copy link
Member

eerkunt commented Jul 1, 2021

Forget about what I wrote above, it looks like @timgates42 will solve this on #516. I should have checked the PR first :)

@eerkunt
Copy link
Member

eerkunt commented Jul 1, 2021

Released 1.3.20 with @timgates42 's PR.

@doniz
Copy link

doniz commented Dec 29, 2022

@eerkunt why are you not compiling as binary in a multi-arch using CI/CD? So it would be possible to download from the releases page according to the OS arch, instead installing all needed dependencies by Python.

@eerkunt
Copy link
Member

eerkunt commented Dec 30, 2022

Actually, this is a very good idea. I avoided that option years ago as creating a static binary package with Python was not really that good. Let me have a look on this.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants