Skip to content

Commit

Permalink
A0-1892: Debian base with GNU linker. (Cardinal-Cryptography#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
deuszx authored Jan 20, 2023
1 parent fc4620d commit 36147f0
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 57 deletions.
85 changes: 32 additions & 53 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,69 +1,51 @@
# Dockerfile building cargo-contract version v2.0.0-beta.1
# Using basic Alpine image.
FROM alpine:3.17 as slimmed-rust

RUN apk add --no-cache gcc
FROM docker.io/bitnami/minideb:bullseye as slimmed-rust

ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH \
RUST_VERSION=1.66.0
RUST_VERSION=nightly-2022-11-28

# Minimal Rust dependencies.
RUN set -eux; \
apkArch="$(apk --print-arch)"; \
case "$apkArch" in \
x86_64) rustArch='x86_64-unknown-linux-musl'; rustupSha256='95427cb0592e32ed39c8bd522fe2a40a746ba07afb8149f91e936cddb4d6eeac' ;; \
aarch64) rustArch='aarch64-unknown-linux-musl'; rustupSha256='7855404cdc50c20040c743800c947b6f452490d47f8590a4a83bc6f75d1d8eda' ;; \
*) echo >&2 "unsupported architecture: $apkArch"; exit 1 ;; \
esac; \
url="https://static.rust-lang.org/rustup/archive/1.25.1/${rustArch}/rustup-init"; \
wget "$url"; \
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
chmod +x rustup-init; \
./rustup-init -y --no-modify-path --profile minimal --component rust-src --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
rm rustup-init; \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
rustup --version; \
cargo --version; \
rustc --version;
RUN set -eux \
&& apt-get update && apt-get -y install wget \
&& dpkgArch="$(dpkg --print-architecture)" \
&& case "${dpkgArch##*-}" in \
amd64) rustArch='x86_64-unknown-linux-gnu' ;; \
arm64) rustArch='aarch64-unknown-linux-gnu' ;; \
*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
esac \
&& url="https://static.rust-lang.org/rustup/dist/${rustArch}/rustup-init" \
&& wget "$url" \
&& chmod +x rustup-init \
&& ./rustup-init -y --no-modify-path --profile minimal --component rust-src --default-toolchain $RUST_VERSION \
&& rm rustup-init \
&& chmod -R a+w $RUSTUP_HOME $CARGO_HOME \
&& rustup --version \
&& cargo --version \
&& rustc --version \
&& apt-get remove -y --auto-remove wget \
&& rm -rf /var/lib/apt/lists/*

FROM slimmed-rust as cc-builder

# This is important, see https://github.com/rust-lang/docker-rust/issues/85
ENV RUSTFLAGS="-C target-feature=-crt-static"

RUN apk update \
&& apk add --no-cache \
git \
musl-dev \
libgcc \
gcc g++ \
gcompat
RUN apt-get -y update && apt-get -y install gcc g++ git

# Use https instead of git so that we don't have to install required for using git://
RUN git clone https://github.com/paritytech/cargo-contract.git
RUN git clone --depth 1 --branch v2.0.0-beta.1 https://github.com/paritytech/cargo-contract.git

WORKDIR ${PWD}/cargo-contract

RUN git fetch origin \
&& git fetch --tags

COPY optimized-build.toml .

RUN git checkout tags/v2.0.0-beta.1

# Apply build optimizations.
RUN cat optimized-build.toml >> Cargo.toml

RUN cargo build --profile optimized

# Copy the binary and clean the directory from compilation dependencies.
RUN cp target/optimized/cargo-contract /usr/local/bin/ \
&& cargo clean

# Clean up Cargo dependencies.
RUN rm -rf ${CARGO_HOME}/"registry" ${CARGO_HOME}/"git"
RUN cat optimized-build.toml >> Cargo.toml \
&& cargo build --profile optimized \
&& cp target/optimized/cargo-contract /usr/local/bin/ \
&& cargo clean \
&& rm -rf ${CARGO_HOME}/"registry" ${CARGO_HOME}/"git"

WORKDIR /

Expand All @@ -74,15 +56,12 @@ RUN rm -rf cargo-contract
#
FROM slimmed-rust as ink-dev

# Update the repository; add without caching dependencies.
# Add required gcc integration (Alpine by default uses musl linker).
RUN apk update \
&& apk add --no-cache \
g++ \
gcompat

COPY --from=cc-builder /usr/local/bin/cargo-contract /usr/local/bin/cargo-contract

# Needed for 'cc' linking
RUN apt-get update && apt-get -y install gcc \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /code

CMD ["cargo", "contract", "build", "--release"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: build-image build-ink-dev-x86_64 build-ink-dev-arm64 test-contract-x86_64 test-contract-arm64

DOCKER_NAME_INK_DEV := cardinal-cryptography/ink-dev
DOCKER_TAG := 0.1.0
DOCKER_TAG := 0.2.0

# Native arch
BUILDARCH := $(shell uname -m)
Expand Down
50 changes: 47 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,51 @@ $ cd my-project
$ ink-build()
```

Or, more flexible:
```sh
function ink-dev() {
docker run --rm -it \
-v ${PWD}:/code \
--platform linux/amd64 \
-u $UID:$(id -g) \
cardinal-cryptography/ink-dev:latest "$@"
}
```

which will now allow for passing in different commands and/or arguments:
```sh
$ ink-dev cargo contract check
$ ink-dev cargo contract build --manifest-path some/other/project/Cargo.toml
```


## Advanced usage

Remember, since mounting volume for the Docker container will mount only that directory recursively any files in the parent directories will not be available/visible inside the container. Below, we present solutions to some more common scenarios in which you might want to use the container.

### Overriding Rust

If your project have similar structure to the following:
```sh
my-app/
├─ ink-project-a/
│ ├─ Cargo.toml
│ ├─ lib.rs
├─ ink-project-b/
│ ├─ Cargo.toml
│ ├─ lib.rs
├─ rust-toolchain
```
where you want to overwrite Rust for all projects inside `my-app`, you will have to mount `my-app` as docker volume. Only then the `rust-toolchain` overrides will be "visible" for both Ink projects.

Example command (assuming `PWD=/my-app`):
```sh
docker run --rm -v ${PWD}:/code cardinal-cryptography/ink-dev:latest cargo contract build --release --manifest-path ink-project-a/Cargo.toml
```

By providing `--manifest-path` we can specify exactly which project we want to build.


### Path dependencies in `Cargo.toml`

If your contract depends on other contracts using its path, example:
Expand All @@ -42,18 +85,19 @@ Then using it as described in previous section will fails with `[ERROR]: cargo m

For these cases, we need to mount additional directories manually:
```sh
docker run \
docker run --rm -it \
-v ${PWD}:/code \
-v ${PWD}/../other-contract:/other-contract
--platform linux/amd64 \
--rm -it cardinal-cryptography/ink-dev:latest \
-u $UID:$(id -g) \
cardinal-cryptography/ink-dev:latest \
cargo contract build --release --quiet
```
Notice the additional `-v ${PWD}/../other-contract:/other-contract` which will mount your dependency so that it's visible in the docker container.

## Building image

> The image is built on Alpine linux to ensure minimal resulting image size. Only minimal Rust dependencies are installed.
> The image is built on minimal Debian linux distribution to ensure minimal resulting image size. Only minimal Rust dependencies are installed.
In the root directory run `make build-image`.

Expand Down

0 comments on commit 36147f0

Please sign in to comment.