Open michaeldclifford opened 3 years ago
Try this - works with canvas@2.9.0 on arm64 and amd64. It also contains ffmpeg a powerful tool to render multiple frames into a video. But if don't work with video delete ffmepg again, as need quite a lot of time to build. Also get rid of the additional fonts as they double the size of the container, if you don't need them.
I have developed this container build in one of our last projects.
### BUILDER CONTAINER IMAGE only used for building
FROM public.ecr.aws/lambda/nodejs:14 as builder
# update (and installing of software without fixed version) means that without code changes behaviour could be slightly different if a new image is created
# therefore every image version should be tested on staging system and deployed as is to production later
# this way we get most important OS security fixes
RUN yum -y update
# only needed for setup (execution of subsequent command "tar")
RUN yum -y install tar xz
# ffmpeg build from source: https://trac.ffmpeg.org/wiki/CompilationGuide/Centos
## ffmpeg build tools and libs like specified in installation guide
RUN yum -y install autoconf automake bzip2 bzip2-devel cmake freetype-devel gcc gcc-c++ git libtool make pkgconfig zlib-devel
RUN mkdir /opt/ffmpeg_sources
WORKDIR /opt/ffmpeg_sources
## ffmepg nasm assembler
RUN curl -O -L https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2
RUN tar xjvf nasm-*.tar.bz2
RUN rm nasm-*.tar.bz2
RUN cd nasm-* && ./autogen.sh
RUN cd nasm-* && ./configure --prefix="/opt/ffmpeg_build" --bindir="/opt/bin"
RUN cd nasm-* && make
RUN cd nasm-* && make install
## ffmpeg yasm assembler
RUN curl -O -L https://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
RUN tar xzvf yasm-*.tar.gz
RUN rm yasm-*.tar.gz
RUN cd yasm-* && ./configure --prefix="/opt/ffmpeg_build" --bindir="/opt/bin"
RUN cd yasm-* && make
RUN cd yasm-* && make install
## ffmpeg libx264 video codec
RUN git clone --branch stable --depth 1 https://code.videolan.org/videolan/x264.git
RUN cd x264 && PKG_CONFIG_PATH="/opt/ffmpeg_build/lib/pkgconfig" ./configure --prefix="/opt/ffmpeg_build" --bindir="/opt/bin" --enable-static
RUN cd x264 && make
RUN cd x264 && make install
## ffmepg mp3 audio codec
RUN curl -O -L https://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
RUN tar xzvf lame-*.tar.gz
RUN rm lame-*.tar.gz
RUN cd lame-* && ./configure --prefix="/opt/ffmpeg_build" --bindir="/opt/bin" --disable-shared --enable-nasm
RUN cd lame-* && make
RUN cd lame-* && make install
## ffmpeg build
RUN curl -O -L https://ffmpeg.org/releases/ffmpeg-5.0.tar.bz2
RUN tar xjvf ffmpeg-*.tar.bz2
RUN rm ffmpeg-*.tar.bz2
RUN cd ffmpeg-* && PKG_CONFIG_PATH="/opt/ffmpeg_build/lib/pkgconfig" ./configure \
--prefix="/opt/ffmpeg_build" \
--pkg-config-flags="--static" \
--extra-cflags="-I/opt/ffmpeg_build/include" \
--extra-ldflags="-L/opt/ffmpeg_build/lib" \
--extra-libs=-lpthread \
--extra-libs=-lm \
--bindir="/opt/bin" \
--enable-gpl \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libx264 \
--enable-nonfree
RUN cd ffmpeg-* && make
RUN cd ffmpeg-* && make install
WORKDIR /var/task
# build tools needed for installation of npm package "canvas"
RUN yum -y install gcc-c++ make
# libraries needed for installation of npm package "canvas"
RUN yum -y install cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel bzip2-devel
# copy only files needed for npm install - so npm install will only be executed again if those files have changed
# .npmrc is needed for the vm-rendering-library to authenticate against nexus
COPY package.json .npmrc ./
# install all npm dependencies including dev dependencies
RUN npm install
# copy all remaining files not excluded in .dockerignore
COPY ./ ./
# build typescript
RUN npm run build
# rename app.js to app.mjs to call ESM module from commonJS
RUN find ./dist -type f -name "*.js" -and -not -name "handler.js" -exec sh -c 'mv "$0" "${0%.js}.mjs"' {} \;
# remove npm dev dependencies as they aren't needed anymore - make node_modules production ready
# RUN npm prune --production
### END OF BUILDER CONTAINER IMAGE
### START OF RUNTIME CONTAINER IMAGE
FROM public.ecr.aws/lambda/nodejs:14
# install again because some dependencies are needed at runtime
RUN yum -y install cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel bzip2-devel
# Non latin characters must be installed
RUN yum -y install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
RUN yum -y install kde-l10n-Chinese
RUN yum -y install kde-l10n-Japanese
RUN yum -y install kde-l10n-Arabic
RUN yum -y install kde-l10n-Korean
RUN yum -y reinstall glibc-common
RUN yum -y install kde-l10n-Chinese.noarch google-noto-sans-traditional-chinese-fonts.noarch google-noto-sans-simplified-chinese-fonts.noarch
RUN yum -y install kde-l10n-Japanese.noarch google-noto-sans-japanese-fonts.noarch
RUN yum -y install kde-l10n-Korean.noarch google-noto-sans-korean-fonts.noarch
RUN yum -y install kde-l10n-Arabic.noarch google-noto-sans-arabic-fonts.noarch
# copy over ffmepg from builder
COPY --from=builder /opt/ffmpeg_sources/ffmpeg-*/ffmpeg /opt/ffmpeglib/ffmpeg
# copy over node_modules from builder
COPY --from=builder /var/task/node_modules ./node_modules
# is set automatically by the docker platform attribute (cpu-arch) - this dockerfile will only work with "*/amd64" or "*/arm64"
ARG TARGETARCH
# manual installation for lambda insights extension, as this seems to be the only way for arm64 (at least right now, arm64 on AWS Lambda is pretty new)
COPY --from=builder /var/task/lambda-insights-extension/${TARGETARCH}/ /opt/
# make lambda insights extension executable
RUN chmod a+x "/opt/extensions/cloudwatch_lambda_agent"
ARG SERVICE_NAME
# copy over only the files from that specific service - rename the folder to service, as dynamic command names in docker are difficult
COPY --from=builder /var/task/dist/${SERVICE_NAME} ./dist/service
# fixing an issue in npm package canvas - must be executed after npm install
ENV LD_PRELOAD=/var/task/node_modules/canvas/build/Release/libz.so.1
ENV NODE_OPTIONS="--experimental-specifier-resolution=node"
# enable the lambda being executed - the correct handler function should be called
CMD ["dist/service/src/lambda/handler.handler"]
Issue
Attempting to use Canvas on Lambda results in the following error:
Context
I'm attempting to use
chartjs-node-canvas
on Lambda.The Installation Guide says that Canvas 2 should work, so long as it is installed on a Linux docker container, so I have used the following Dockerfile
to set up a container, and then run
npm install
inside the container, before packaging up thenode_modules
andoutput
folders into one.zip
file.Unzipping the file locally shows that
canvas.node
exists at/node_modules/canvas/build/Release/canvas.node
, but the error mentioned above occurs when running the lambda.Things I've tried that (sadly) haven't worked (yet)
node_modules
folder relative to theindex.js
file — this made zero difference as Lambda no longer seems to care where the folder is, so long as there's a name matchchmod +x ./node_modules/canvas/build/Release/canvas.node
Steps to Reproduce
Run the following as part of a Lambda function
Your Environment
npm list canvas
Environment node v14.18.1 on AmazonLinux2 Docker container node v14.18.1 on macOS 11.5.2