kovetskiy / mark

Sync your markdown files with Confluence pages.
https://samizdat.dev
Other
972 stars 143 forks source link

Add alternate minimal Dockerfile #434

Open stephenpaulger opened 3 months ago

stephenpaulger commented 3 months ago

I've added a more minimal Dockerfile that uses an alpine base image, the resulting image is under 50MB and contains no software with known vulnerabilities.

The standard mark image requires chrome in order for mermaid-go to work so this Dockerfile isn't a replacement it is an alternative that should work for anyone that doesn't need mermaid-go. Unfortunately the chromedp base image is large and contains vulnerable versions of software that, as far as I can tell, have no bearing on mark's functionality, rather than make an assessment for each vulnerability I thought it'd be easier to avoid those unused pieces of software.

I've made no effort to make this fail gracefully should someone try to use mermaid-go but I think for any other use case it should work just as well. I chose alpine as the base image as scratch doesn't have a shell which is useful when using the image in CI, busybox may be another option.

tmeckel commented 3 months ago

@stephenpaulger when linking GO statically -extldflags '-static' you might could use FROM SCRATCH, what would reduce the overhead size of the Container Image to 0 Kelvin 😁 i.e. no overhead at all.

stephenpaulger commented 2 months ago

@tmeckel I did start with scratch but quickly realised I needed a shell to use it in CI, it only adds a very small amount by using alpine, mark has a CI mode so I assume that's a common use case.

tmeckel commented 2 months ago

@stephenpaulger now you've made me curious! Why'd you need shell support in the container image? Is it because of mark itself?

stephenpaulger commented 2 months ago

@tmeckel No, not mark itself. If you use gitlab you might have a CI config something like.

deploy-to-confluence:
  stage: deploy
  image:
    name: kovetskiy/mark:9.11.1
  script:
    - mark --ci=true --drop-h1 -p $CONFLUENCE_TOKEN --space $CONFLUENCE_SPACE --base-url $CONFLUENCE_BASEURL --files "*.md"

The part within script is run within the container itself in a shell, I did experiment with using the entrypoint to run mark instead but I wasn't able to get it to work, I think because the variables aren't interpreted, so I went back to what worked with the standard mark image which needs a shell in the container.

https://docs.gitlab.com/ee/ci/docker/using_docker_images.html

mrueg commented 2 months ago

The new docker-headless-shell image is using bookworm-slim, which I think should be fine for this purpose. If the libraries installed by docker-headless + chrome make this feel big, I'd suggest to parametrize the runtime image instead of having a second Dockerfile.

stephenpaulger commented 2 months ago

The main issue for me is not the size directly but the detected CVEs. If I build and scan each image with trivy.

docker build --platform=linux/amd64,linux/arm64 -t mark:9.12.0 -f Dockerfile .
trivy image mark:9.12.0
mark:9.12.0 (debian 12.5)
=========================
Total: 150 (UNKNOWN: 0, LOW: 92, MEDIUM: 27, HIGH: 30, CRITICAL: 1)
docker build --platform=linux/amd64,linux/arm64 -t mark:9.12.0-alpine -f Dockerfile.minimal .
trivy image mark:9.12.0-alpine
mark:9.12.0-alpine (alpine 3.19.1)

Total: 2 (UNKNOWN: 0, LOW: 2, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

I don't think for either image that it's likely those CVEs are reachable from mark especially as I'm not using mermaid but not having them in the image means I don't need to check or justify their presence.

I'm not very familiar with parameterising base images, I understand it can be passed with an ARG but the main image relies on apt-get which isn't present in alpine.