--- title: "Deploy a custom container image" description: "Deploy your own public Docker image as a Functions function from its Dockerfile, with the architecture, user, and port rules the image must follow." content_type: "how-to" product: "functions" platform: "MyAccount" url: "/myaccount/functions/how-to/deploy-a-custom-container-image/" topic: ["create"] relationships: {"requires":["/myaccount/functions/how-to/create-a-function/"]} --- # Deploy a custom container image Run your own Docker image as a function, from a `Dockerfile` that points at the image. Use **Custom Container Image** when your application has its own framework or runtime that the built-in templates do not cover. A container function runs on CPU hardware and is billed as a CPU function. See [Billing](/myaccount/functions/concepts/billing/). ## Before you begin You need a public Docker image that is built for `linux/amd64` and runs as a non-root user. A private image, such as one in E2E Container Registry, cannot be used. By default the container must listen on port 8080. If your container listens on a different port, add an environment variable with this name, and set its value to the port number: ```text __PORT__ ``` Functions reserves the name `PORT`, so choose another. ## Write the Dockerfile With **Custom Container Image**, the editor has two tabs. The `Dockerfile` tab holds the file the platform builds. The `DOCS.md` tab holds the platform's guidelines for writing that `Dockerfile`. The template's `Dockerfile` sets the architecture and the non-root user. It reads: ```dockerfile # Set your desired public base image here in BASE_IMAGE # ARG BASE_IMAGE= ARG BASE_IMAGE=e2efaasplatform/react-sample FROM --platform=linux/amd64 ${BASE_IMAGE} # Do not modify the following configurations # These ensure the container runs securely as a non-root user USER 1001 # You can add your custom instructions below this line [Optional] ``` Of the template's lines, change only the BASE_IMAGE line. Set it to the address of your public image. Keep `USER 1001` as it is: the template marks it "Do not modify". Add your own instructions below the last comment. ## Create the function To upload the files as a ZIP instead, include both `Dockerfile` and `DOCS.md`. See [Upload code as a ZIP](/myaccount/functions/how-to/upload-code-as-a-zip/). 1. In **Create Function**, choose **Custom Container Image**. 2. In the `Dockerfile` tab, set the BASE_IMAGE argument to your image. 3. Fill in the function name and, under **System Configuration**, the memory and timeout, as in [Create a function](/myaccount/functions/how-to/create-a-function/). 4. (Optional) If your container listens on a port other than 8080, add the port environment variable under **Function Configuration**, set to the port number. See [Before you begin](#before-you-begin). 5. (Optional) To keep instances always running, turn on **Enable Dedicated Replica**. See [Keep a function ready with dedicated replicas](/myaccount/functions/how-to/keep-a-function-ready-with-dedicated-replicas/). 6. Click **Create**. The function builds and deploys, then reads **Running** once your container is up. ## Check that the function is running When the function reads **Running**, its public HTTPS **URL** is ready. Call it to confirm your container answers. See [Call a function](/myaccount/functions/how-to/call-a-function/). If the function reads **Failed**, open its page and read the **Build Logs** tab. See [Troubleshooting Functions](/myaccount/functions/troubleshooting/functions/). You now have a function running your own container image. To compare it with the built-in runtimes, see [Runtimes and hardware](/myaccount/functions/concepts/runtimes-and-hardware/).