# # NOTE: THIS DOCKERFILE IS GENERATED FROM "Dockerfile.template" VIA # "generate-dockerfiles.sh". # # PLEASE DO NOT EDIT IT DIRECTLY. # {{#debian}} # Python is needed for building libnss. # Use it as a common base. FROM python:3.10.1-slim-buster {{/debian}} {{#alpine}} FROM alpine:3.15.0 as builder {{/alpine}} WORKDIR /build # Common dependencies {{#debian}} RUN apt-get update && \ apt-get install -y git ninja-build cmake curl zlib1g-dev {{/debian}} {{#alpine}} RUN apk add git build-base make cmake ninja curl zlib-dev patch linux-headers python3 python3-dev {{/alpine}} # The following are needed because we are going to change some autoconf scripts, # both for libnghttp2 and curl. {{#debian}} RUN apt-get install -y autoconf automake autotools-dev pkg-config libtool {{/debian}} {{#alpine}} RUN apk add autoconf automake pkgconfig libtool {{/alpine}} {{#firefox}} # Dependencies for building libnss # See https://firefox-source-docs.mozilla.org/security/nss/build.html#mozilla-projects-nss-building {{#debian}} RUN apt-get install -y mercurial python3-pip {{/debian}} {{#alpine}} RUN apk add mercurial py3-pip clang-analyzer {{/alpine}} {{#debian}} # curl tries to load the CA certificates for libnss. # It loads them from /usr/lib/x86_64-linux-gnu/nss/libnssckbi.so, # which is supplied by libnss3 on Debian/Ubuntu RUN apt-get install -y libnss3 {{/debian}} {{/firefox}} {{#chrome}} # Dependencies for downloading and building BoringSSL {{#debian}} RUN apt-get install -y g++ golang-go unzip {{/debian}} {{#alpine}} RUN apk add g++ go unzip {{/alpine}} {{/chrome}} # Download and compile libbrotli ARG BROTLI_VERSION=1.0.9 RUN curl -L https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz -o brotli-${BROTLI_VERSION}.tar.gz && \ tar xf brotli-${BROTLI_VERSION}.tar.gz RUN cd brotli-${BROTLI_VERSION} && \ mkdir build && cd build && \ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./installed .. && \ cmake --build . --config Release --target install {{#firefox}} # Needed for building libnss RUN pip install gyp-next ARG NSS_VERSION=nss-3.77 # This tarball is already bundled with nspr, a dependency of libnss. ARG NSS_URL=https://ftp.mozilla.org/pub/security/nss/releases/NSS_3_77_RTM/src/nss-3.77-with-nspr-4.32.tar.gz # Download and compile nss. RUN curl -o ${NSS_VERSION}.tar.gz ${NSS_URL} RUN tar xf ${NSS_VERSION}.tar.gz && \ cd ${NSS_VERSION}/nss && \ ./build.sh -o --disable-tests --static --python=python3 {{/firefox}} {{#chrome}} # BoringSSL doesn't have versions. Choose a commit that is used in a stable # Chromium version. ARG BORING_SSL_COMMIT=3a667d10e94186fd503966f5638e134fe9fb4080 RUN curl -L https://github.com/google/boringssl/archive/${BORING_SSL_COMMIT}.zip -o boringssl.zip && \ unzip boringssl && \ mv boringssl-${BORING_SSL_COMMIT} boringssl # Compile BoringSSL. # See https://boringssl.googlesource.com/boringssl/+/HEAD/BUILDING.md COPY patches/boringssl-*.patch boringssl/ RUN cd boringssl && \ for p in $(ls boringssl-*.patch); do patch -p1 < $p; done && \ mkdir build && cd build && \ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=on -GNinja .. && \ ninja # Fix the directory structure so that curl can compile against it. # See https://everything.curl.dev/source/build/tls/boringssl RUN mkdir boringssl/build/lib && \ ln -s ../crypto/libcrypto.a boringssl/build/lib/libcrypto.a && \ ln -s ../ssl/libssl.a boringssl/build/lib/libssl.a && \ cp -R boringssl/include boringssl/build {{/chrome}} ARG NGHTTP2_VERSION=nghttp2-1.46.0 ARG NGHTTP2_URL=https://github.com/nghttp2/nghttp2/releases/download/v1.46.0/nghttp2-1.46.0.tar.bz2 # Download nghttp2 for HTTP/2.0 support. RUN curl -o ${NGHTTP2_VERSION}.tar.bz2 -L ${NGHTTP2_URL} RUN tar xf ${NGHTTP2_VERSION}.tar.bz2 # Compile nghttp2 RUN cd ${NGHTTP2_VERSION} && \ ./configure --prefix=/build/${NGHTTP2_VERSION}/installed --with-pic --disable-shared && \ make && make install # Download curl. ARG CURL_VERSION=curl-7.84.0 RUN curl -o ${CURL_VERSION}.tar.xz https://curl.se/download/${CURL_VERSION}.tar.xz RUN tar xf ${CURL_VERSION}.tar.xz # Patch curl and re-generate the configure script COPY patches/curl-*.patch ${CURL_VERSION}/ RUN cd ${CURL_VERSION} && \ for p in $(ls curl-*.patch); do patch -p1 < $p; done && \ autoreconf -fi # Compile curl with nghttp2, libbrotli and nss (firefox) or boringssl (chrome). # Enable keylogfile for debugging of TLS traffic. RUN cd ${CURL_VERSION} && \ ./configure --prefix=/build/install \ --enable-static \ --disable-shared \ --with-nghttp2=/build/${NGHTTP2_VERSION}/installed \ --with-brotli=/build/brotli-${BROTLI_VERSION}/build/installed \ {{#firefox}} --with-nss=/build/${NSS_VERSION}/dist/Release \ --with-nss-deprecated \ CFLAGS="-I/build/${NSS_VERSION}/dist/public/nss -I/build/${NSS_VERSION}/dist/Release/include/nspr" \ {{/firefox}} {{#chrome}} --with-openssl=/build/boringssl/build \ LIBS="-pthread" \ CFLAGS="-I/build/boringssl/build" \ {{/chrome}} USE_CURL_SSLKEYLOGFILE=true && \ make && make install RUN mkdir out && \ {{#firefox}} cp /build/install/bin/curl-impersonate-ff out/ && \ ln -s curl-impersonate-ff out/curl-impersonate && \ {{/firefox}} {{#chrome}} cp /build/install/bin/curl-impersonate-chrome out/ && \ ln -s curl-impersonate-chrome out/curl-impersonate && \ {{/chrome}} strip out/curl-impersonate # Verify that the resulting 'curl' has all the necessary features. RUN ./out/curl-impersonate -V | grep -q zlib && \ ./out/curl-impersonate -V | grep -q brotli && \ ./out/curl-impersonate -V | grep -q nghttp2 && \ ./out/curl-impersonate -V | grep -q -e NSS -e BoringSSL # Verify that the resulting 'curl' is really statically compiled RUN ! (ldd ./out/curl-impersonate | grep -q -e libcurl -e nghttp2 -e brotli -e ssl -e crypto) RUN rm -Rf /build/install # Re-compile libcurl dynamically RUN cd ${CURL_VERSION} && \ ./configure --prefix=/build/install \ --with-nghttp2=/build/${NGHTTP2_VERSION}/installed \ --with-brotli=/build/brotli-${BROTLI_VERSION}/build/installed \ {{#firefox}} --with-nss=/build/${NSS_VERSION}/dist/Release \ --with-nss-deprecated \ CFLAGS="-I/build/${NSS_VERSION}/dist/public/nss -I/build/${NSS_VERSION}/dist/Release/include/nspr" \ {{/firefox}} {{#chrome}} --with-openssl=/build/boringssl/build \ LIBS="-pthread" \ CFLAGS="-I/build/boringssl/build" \ {{/chrome}} USE_CURL_SSLKEYLOGFILE=true && \ make clean && make && make install # Copy libcurl-impersonate and symbolic links RUN cp -d /build/install/lib/libcurl-impersonate* /build/out {{#firefox}} RUN ver=$(readlink -f ${CURL_VERSION}/lib/.libs/libcurl-impersonate-ff.so | sed 's/.*so\.//') && \ major=$(echo -n $ver | cut -d'.' -f1) && \ ln -s "libcurl-impersonate-ff.so.$ver" "out/libcurl-impersonate.so.$ver" && \ {{/firefox}} {{#chrome}} RUN ver=$(readlink -f ${CURL_VERSION}/lib/.libs/libcurl-impersonate-chrome.so | sed 's/.*so\.//') && \ major=$(echo -n $ver | cut -d'.' -f1) && \ ln -s "libcurl-impersonate-chrome.so.$ver" "out/libcurl-impersonate.so.$ver" && \ {{/chrome}} ln -s "libcurl-impersonate.so.$ver" "out/libcurl-impersonate.so" && \ strip "out/libcurl-impersonate.so.$ver" # Verify that the resulting 'libcurl' is really statically compiled against its # dependencies. RUN ! (ldd ./out/curl-impersonate | grep -q -e nghttp2 -e brotli -e ssl -e crypto) # Wrapper scripts {{#firefox}} COPY curl_ff* out/ {{/firefox}} {{#chrome}} COPY curl_chrome* curl_edge* curl_safari* out/ {{/chrome}} {{#alpine}} # Replace /usr/bin/env bash with /usr/bin/env ash RUN sed -i 's@/usr/bin/env bash@/usr/bin/env ash@' out/curl_* {{/alpine}} RUN chmod +x out/curl_* {{#alpine}} # When using alpine, create a final, minimal image with the compiled binaries # only. FROM alpine:3.15.0 {{#firefox}} # curl tries to load the CA certificates for libnss. # It loads them from /usr/lib/libnssckbi.so, # which is supplied by 'nss' on alpine. RUN apk add --no-cache nss {{/firefox}} # Copy curl-impersonate from the builder image COPY --from=builder /build/install /usr/local # Wrapper scripts COPY --from=builder /build/out/curl_* /usr/local/bin/ {{/alpine}}