Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Push multi-arch images #38

Merged
merged 33 commits into from
May 5, 2023
Merged

Push multi-arch images #38

merged 33 commits into from
May 5, 2023

Conversation

ddelange
Copy link
Contributor

@ddelange ddelange commented Jan 16, 2023

Motivation

Create multi-platform images for modelmesh-runtime-adapter images.

Modifications

  • build for platforms linux/amd64, linux/arm64 (linux/ppc64le, linux/s390x are not supported by tensorflow)
  • utilize Docker build cache for pip and dnf installs as well as go builds
  • build on pull_request as well as on push to catch build breaks during PR review;
    only push images to DockerHub on PR merge (push to main)
  • upgrade runtime image base from ubi-minimal:8.4 to 8.7
  • use ubi8/go-toolset:1.17 for developer image instead of ubi8/ubi-minimal:8.4
  • update deprecated checkout action
  • fix infinite docker inside docker bug when running make run fmt inside the developer container

Related PRs

Resolves kserve/modelmesh-serving#162

Signed-off-by: ddelange <14880945+ddelange@users.noreply.github.com>
Signed-off-by: ddelange <14880945+ddelange@users.noreply.github.com>

Signed-off-by: ddelange <14880945+ddelange@users.noreply.github.com>
Signed-off-by: ddelange <14880945+ddelange@users.noreply.github.com>
@ckadner ckadner requested review from ckadner and njhill and removed request for animeshsingh and chinhuang007 January 20, 2023 23:08
@ckadner
Copy link
Member

ckadner commented Jan 21, 2023

To avoid some of the arch related errors while installing libraries, we should probably use ubi8/go-toolset as base image instead of ubi8/minimal. Should also help to avoid complexities of building or even just installing go inside the Dockerfile

Alternatively, we could add another variable / docker build ARG for the etcd installation inside the Docker image

https://docs.docker.com/build/building/multi-platform/#building-multi-platform-images

... A list of build arguments like BUILDPLATFORM and TARGETPLATFORM is available automatically inside your Dockerfile and can be leveraged by the processes running as part of your build.

https://blog.thesparktree.com/docker-multi-arch-github-actions#architecture-specific-dockerfile-instructions

TARGETARCH - architecture component of TARGETPLATFORM

https://github.com/kserve/modelmesh-runtime-adapter/blob/main/Dockerfile#L44

... https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz should be
... https://golang.org/dl/go${GOLANG_VERSION}.linux-${TARGETARCH}.tar.gz

Archive files listed on the corresponding download page:
https://go.dev/dl/

  • go1.17.13.linux-amd64.tar.gz
  • go1.17.13.linux-arm64.tar.gz
  • go1.17.13.linux-armv6l.tar.gz
  • go1.17.13.linux-ppc64le.tar.gz
  • go1.17.13.linux-s390x.tar.gz

Default in the Dockerfile should probably be:

ARG TARGETARCH=amd64

But we might have to disable s390x for the missing gRPC/ProtoC libraries/executable

ckadner added 4 commits March 30, 2023 14:22
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
ckadner added 7 commits March 31, 2023 03:10
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
ckadner added 6 commits April 11, 2023 21:43
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
The directory '/opt/app-root/src/.cache/pip' or its parent
directory is not owned by the current user and caching wheels
has been disabled

Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
@ckadner
Copy link
Member

ckadner commented Apr 12, 2023

@tjohnson31415 -- thanks for the pointer to not override the TARGETOS and TARGETARCH ARGs.

ckadner added 2 commits April 12, 2023 02:11
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Copy link
Contributor

@tjohnson31415 tjohnson31415 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirmed that I could build images with binaries for two different CPU archs using the approach coded up here.

Cool Stuff!

Dockerfile Show resolved Hide resolved
Dockerfile Show resolved Hide resolved
Makefile Outdated
@@ -49,4 +47,4 @@ proto.compile:
$(eval $(RUN_ARGS):;@:)

# Remove $(MAKECMDGOALS) if you don't intend make to just be a taskrunner
.PHONY: all $(MAKECMDGOALS)
.PHONY: all build build.develop develop run test fmt proto.compile $(MAKECMDGOALS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think $(MAKECMDGOALS) will cover most of these; it injects the set of targets passed into make on the cmd-line. The only explicit .PHONY you need then are ones that are dependent targets (so build.develop should be in here).
Or its fine to make this list explicit with all targets but then don't need $(MAKECMDGOALS) in here too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I learned something and reinstated the original line :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though the original line also has a problem I think. $(MAKECMDGOALS) is the set of goals specified on the cmd-line, but more targets will run if any of those goals have dependencies. So .PHONY: all $(MAKECMDGOALS) is only sufficient if no targets in the Makefile have dependencies. If there is a dependency, it will not be .PHONY unless explicitly listed. In this case, build.develop should still be in there.

So adding all the targets to .PHONY isn't a bad idea IMO, but there's no reason to add them all and also have $(MAKECMDGOALS).

Makefile hackery 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is tricky to understand -- and apparently was not understood by all developers who made updates to the Makefile before ;-) -- I suggest we go with explicitly listing of all goals.
However, in the current form, this still leaves the door wide open for future developers who add new goals (or remove unused ones, or rename existing ones) to overlook/forget to update the .PHONY pseudo target at the end of the Makefile. So I would prefer to “tag” each individual goal like so:

.PHONY: fmt
fmt:
	./scripts/fmt.sh

.PHONY: test
test:
	go test -coverprofile cover.out `go list ./...`

This way, the .PHONY "tag" would get deleted when the corresponding target gets deleted (or renamed along with renaming a target) and when new targets are added, very likely an existing target would be used as a “template” and the .PHONY “tag” would get copy-pasted or added for sheer “consistency” by the uninitiated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makefiles are fun 😅 I came across a help command that regexes double hashtag above the command, and forms a helptext https://github.com/ddelange/mapply/blob/0.1.21/Makefile

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ddelange -- sorry I completely missed your comment. I have done a similar thing in the past as well here using grep and awk

Do you want to open a PR for this, in this and the other 4 ModelMesh repos?

.github/workflows/build-and-push.yml Show resolved Hide resolved
Dockerfile Show resolved Hide resolved
Dockerfile Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
@ckadner
Copy link
Member

ckadner commented Apr 27, 2023

Thanks @tjohnson31415 -- I updated the PR with the straight-forward changes you suggested and resolved the corresponding conversations.

I left the others as unresolved for you to respond :-)
https://github.com/kserve/modelmesh-runtime-adapter/pull/38/files#conversations-menu

@ckadner ckadner requested a review from tjohnson31415 April 28, 2023 02:14
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Dockerfile Outdated
Comment on lines 34 to 35
ARG PIP_CACHE_DIR=/root/.cache/pip
RUN --mount=type=cache,target=/root/.cache/pip \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I've been experimenting with this a bit. Does this match your understanding?

  • the $HOME for root in go-toolset is not /root/ so we need to set the PIP_CACHE_DIR env var to configure pip's cache directory
  • ARG interpolation doesn't work in the --mount, so the value is copied instead of using target=$PIP_CACHE_DIR

If that's the case, I think it is slightly cleaner to set the PIP_CACHE_DIR env var in the RUN command since the ARG is not really configurable.

Though I also found moby/buildkit#815 and it sounds like using ARGs in --mount can now work, but requires a newer Dockerfile syntax # syntax=docker/dockerfile:1.3.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi 👋

Unless the host system (github actions) would build python wheels from source, there is no speedup from mounting pip's cache dir. We generally recommend to set PIP_NO_CACHE_DIR and rely on docker layer caching by running pip install before copying over source code. That way, you reuse the registry's layer as long as your requirements.txt doesn't change. Here's a live multi-arch example that combines a compiled C binary (libpostal) with python builds that use it.

Copy link
Member

@ckadner ckadner May 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good comments/questions @tjohnson31415 @ddelange !

Unless the host system (github actions) would build python wheels from source, there is no speedup from mounting pip's cache dir.

The cache mount is useful for subsequent builds, multi-stage and multi-platform builds. I have seen it being used and speedup the GitHub action builds quite a bit, with significant time savings for installing grpc and tensorflow

the $HOME for root in go-toolset is not /root/ so we need to set the PIP_CACHE_DIR env var to configure pip's cache directory

Yes, otherwise we see this error:

#13 12.99 The directory '/opt/app-root/src/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
#13 13.00 The directory '/opt/app-root/src/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.

However, for pip, the inline --cache-dir CLI flag did not set the cache correctly for both HTTP download and the Wheel cache directories. So I use the ARG PIP_CACHE_DIR=/root/.cache/pip which works for both.

ARG interpolation doesn't work in the --mount, so the value is copied instead of using target=$PIP_CACHE_DIR

Yes. I have not tried the new syntax # syntax=docker/dockerfile:1.3.0 though. That's a good find.


References:

ckadner added 3 commits May 4, 2023 15:14
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Signed-off-by: Christian Kadner <ckadner@us.ibm.com>
Copy link
Contributor

@tjohnson31415 tjohnson31415 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kserve-oss-bot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ddelange, tjohnson31415

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ckadner ckadner merged commit cc46172 into kserve:main May 5, 2023
@ddelange
Copy link
Contributor Author

ddelange commented May 5, 2023

awesome work @ckadner!!

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

Successfully merging this pull request may close these issues.

Quick start not working for Mac M1 laptops
4 participants