Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

AWS Lambda Rust docker builder πŸ‘ πŸ¦€ 🐳 Build Status

πŸ€” about

This docker image extends lambda ci provided.al2 builder docker image, a faithful reproduction of the actual AWS "provided.al2" Lambda runtime environment, and installs rustup and the stable rust toolchain.

This provides a build environment, consistent with your target execution environment for predictable results.

πŸ“¦ install

Tags for this docker image follow the naming convention softprops/lambda-rust:{version}-rust-{rust-stable-version} where {rust-stable-version} is a stable version of rust.

You can find a list of available docker tags here

πŸ’‘ If you don't find the version you're looking for, please open a new github issue to publish one

You can also depend directly on softprops/lambda-rust:latest for the most recently published version.

🀸 usage

The default docker entrypoint will build a packaged release optimized version of your Rust artifact under target/lambda/release to isolate the lambda specific build artifacts from your host-local build artifacts.

⚠️ Note: you can switch from the release profile to a custom profile like dev by providing a PROFILE environment variable set to the name of the desired profile. i.e. -e PROFILE=dev in your docker run

⚠️ Note: you can include debug symbols in optimized release build binaries by setting DEBUGINFO. By default, debug symbols will be stripped from the release binary and set aside in a separate .debug file.

You will want to volume mount /code to the directory containing your cargo project.

You can pass additional flags to cargo, the Rust build tool, by setting the CARGO_FLAGS docker env variable.

Unzipped boostrap and boostrap.debug files are always available under target/lambda/${PROFILE}/output/${BIN} dir. If you want only them and don't need a .zip archive (e.g. for when running lambdas locally) pass -e PACKAGE=false flag. More on that in local testing.

A typical docker run might look like the following.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

πŸ’‘ The -v (volume mount) flags for /cargo/{registry,git} are optional but when supplied, provides a much faster turn around when doing iterative development

Note that -u $(id -u):$(id -g) argument is crucial for the container to produce artifacts owned by the current host user, otherwise you won't be able to rm -rf target/lambda or run cargo update, because the container will write artifacts owned by root docker user to target/lambda and ./cargo/{registry,git} dirs which will break your dev and/or ci environment.

You should also ensure that you do have ${HOME}/.cargo/{registry,git} dirs created on your host machine, otherwise docker will create them automatically and assign root user as an owner for these dirs which is unfortunate...

If you are using Windows, the command above may need to be modified to include a BIN environment variable set to the name of the binary to be build and packaged

$ docker run --rm \
-u $(id -u):$(id -g) \
+ -e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust

For more custom codebases, the '-w' argument can be used to override the working directory. This can be especially useful when using path dependencies for local crates.

$ docker run --rm \
-u $(id -u):$(id -g) \
-v ${PWD}/lambdas/mylambda:/code/lambdas/mylambda \
-v ${PWD}/libs/mylib:/code/libs/mylib \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
-w /code/lambdas/mylambda \
softprops/lambda-rust

βš“ using hooks

If you want to customize certain parts of the build process, you can leverage hooks that this image provides. Hooks are just shell scripts that are invoked in a specific order, so you can customize the process as you wish. The following hooks exist:

  • install: run before cargo build - useful for installing native dependencies on the lambda environment
  • build: run after cargo build, but before packaging the executable into a zip - useful when modifying the executable after compilation
  • package: run after packaging the executable into a zip - useful for adding extra files into the zip file

The hooks' names are predefined and must be placed in a directory .lambda-rust in the project root.

You can take a look at an example here.

πŸ”¬ local testing

Once you've built a Rust lambda function artifact, the provided.al2 runtime expects deployments of that artifact to be named "bootstrap". The lambda-rust docker image builds a zip file, named after the binary, containing your binary file renamed to "bootstrap" for you, but zip file creation is unnecessary for local development.

In order to prevent the creation of an intermediate .zip artifact when testing your lambdas locally, pass -e PACKAGE=false during the build. After that the necessary output (not zipped) is available under target/lambda/{profile}/output/{your-lambda-binary-name} dir. You will see both bootstrap and bootstrap.debug files there.

⚠️ Note:PACKAGE=false prevents package hook from running.

You can then invoke this bootstap executable with the lambda-ci docker image for the provided.al2 AWS lambda runtime with a one off container.

# Build your function skipping the zip creation step# You may pass `-e PROFILE=dev` to build using dev profile, but here we use `release`
docker run \
-u $(id -u):$(id -g) \
-e PACKAGE=false \
-e BIN={your-binary-name} \
-v ${PWD}:/code \
-v ${HOME}/.cargo/registry:/cargo/registry \
-v ${HOME}/.cargo/git:/cargo/git \
softprops/lambda-rust
# start a one-off docker container replicating the "provided.al2" lambda runtime# awaiting an event to be provided via stdin
$ docker run \
-i -e DOCKER_LAMBDA_USE_STDIN=1 \
--rm \
-v ${PWD}/target/lambda/release/output/{your-binary-name}:/var/task:ro,delegated \
lambci/lambda:provided.al2
# provide an event payload via stdin (typically a json blob)# Ctrl-D to yield control back to your function

You may find the one-off container less than ideal if you wish to trigger your lambda multiple times. For these cases try using the "stay open" mode of execution.

# start a long running docker container replicating the "provided" lambda runtime# listening on port 9001
$ unzip -o \
target/lambda/release/{your-binary-name}.zip \
-d /tmp/lambda && \
docker run \
--rm \
-v /tmp/lambda:/var/task:ro,delegated \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
lambci/lambda:provided.al2

In a separate terminal, you can invoke your function with curl

The -d flag is a means of providing your function's input.

$ curl -d '{}' \
http://localhost:9001/2015-03-31/functions/myfunction/invocations

You can also use the aws cli to invoke your function locally. The --payload is a means of providing your function's input.

$ aws lambda invoke \
--endpoint http://localhost:9001 \
--cli-binary-format raw-in-base64-out \
--no-sign-request \
--function-name myfunction \
--payload '{}' out.json \
&& cat out.json \
&& rm -f out.json

🀸🀸 usage via cargo aws-lambda subcommand

A third party cargo subcommand exists to compile your code into a zip file and deploy it. This comes with only rust and docker as dependencies.

Setup

$ cargo install cargo-aws-lambda

To compile and deploy in your project directory

$ cargo aws-lambda {your aws function's full ARN} {your-binary-name}

To list all options

$ cargo aws-lambda --help

More instructions can be found here.

Doug Tangren (softprops) 2020

About

🐳 πŸ¦€ a dockerized lambda build env for rust applications with added libpq

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages