> ## Documentation Index
> Fetch the complete documentation index at: https://dev.writer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy with Docker

<Tip>
  To deploy on the Writer cloud see instructions [here](/framework/quickstart#deploying-on-writer-cloud).
</Tip>

You can use Docker to deploy Framework anywhere. If you're an experienced Docker user, you may want to go straight to the provided Dockerfile.

## Creating a Docker image

<Steps>
  <Step title="Verify docker installation">
    Make sure you have Docker installed on your system.
  </Step>

  <Step title="Navigate to your app's folder">
    Open a terminal and navigate to your app’s folder.
  </Step>

  <Step title="Set up Python environment">
    Create a `pyproject.toml` file using `poetry init` and install `writer` using `poetry add writer`.
  </Step>
</Steps>

A Dockerfile is a file with instructions that tell Docker how to build your image. It must be named `Dockerfile`. You can use the following as-is, or as a starting point. It should be saved in your app's folder, together with `main.py` and `.wf/`.

```docker theme={null}
FROM python:3.10-bullseye
RUN apt-get update -y && mkdir /app
RUN apt-get install build-essential cmake python3-dev -y
COPY . /app
WORKDIR /app
RUN pip3 install poetry
RUN poetry config virtualenvs.create false
RUN poetry install --only main
ENTRYPOINT [ "writer", "run" ]
EXPOSE 8080
CMD [ ".",  "--port", "8080", "--host", "0.0.0.0" ] 
```

<Note>
  This Dockerfile is just a guideline.
  It uses an official Python slim base image with a multistage build to reduce the size of the built image.
  If you're a Docker expert, feel free to work on your own `Dockerfile`. Framework is, after all, a standard Python package.
</Note>

To build the image, use `docker build . -t ` followed by an image tag, which you're free to choose and will locally identify your image.

```sh theme={null}
docker build . -t my_framework_app
```

<Warning>
  By default, Docker builds images in the architecture it's being run on. If you're working with an ARM computer, such as a Mac M2 or a Raspberry Pi, Docker will build an ARM image. Most cloud services will only accept x86 images. You can use another computer (or virtual machine) to build the image, or you can use [Docker buildx](https://docs.docker.com/build/building/multi-platform/).
</Warning>

## Publishing your Docker image

Once your Docker image has been built, you can publish it to a registry. This is a place where Docker images are stored and made available to other services.

We recommend using Docker Hub; it has a generous free tier, it's very easy to set up and it's widely supported. However, you can choose to use another service such as Azure Container Registry. To use Docker Hub, you'll need to sign up for an account.

You can push your image using the following commands.

```sh theme={null}
# Login to Docker Hub
docker login

# Push the image
# Replace "my_writer_app" for the tag you've previously chosen
# Replace "my_user" for your user on Docker Hub
docker tag my_writer_app:latest my_user/my_writer_app:latest
docker push my_user/my_writer_app:latest
```

If your image is public, anyone can now run the following command and start the app. It's important to bind the port to a port in the host machine. The command below binds port 8080 in the Docker image to port 8080 in the host.

```sh theme={null}
docker run -p 8080:8080 my_user/my_framework_app
```

Go on your browser to [http://localhost:8080](http://localhost:8080) to check everything is working as expected.

## Deploying your Docker image

As mentioned earlier, once the image is a registry, it can be spun up by others. After trying a few options, we recommend using Google Cloud Run. Its free tier is generous and SSL works out of the box.

<img src="https://mintcdn.com/writer/eBiCs3I5_-mSTcT-/framework/images/deploy-with-docker.google-cloud-run.png?fit=max&auto=format&n=eBiCs3I5_-mSTcT-&q=85&s=af8ba51ab1ea3dbdaf59274e7e6b2274" alt="Run and Share - Google Cloud Run" width="2291" height="1144" data-path="framework/images/deploy-with-docker.google-cloud-run.png" />

Cloud Run can be configured in just one page. It takes the image from a registry and makes it available via a URL, with SSL enabled by default. We recommend the following settings:

<AccordionGroup>
  <Accordion title="Instance specifications">
    Minimum 0 instances, maximum 4 instances. This range is suitable unless your app needs to serve several thousands of users.
  </Accordion>

  <Accordion title="Connection settings">
    Set the request timeout to the maximum allowed and enable Session Affinity. This ensures that WebSocket connections are not unnecessarily dropped.
  </Accordion>

  <Accordion title="Resource allocation">
    Allocate 2GB of memory and 2 vCPUs. This configuration will likely be enough to comfortably run a simple app. However, you can probably manage with much less—512MB of memory and 1 vCPU—if your app isn’t too demanding and you don’t expect much traffic.
  </Accordion>
</AccordionGroup>
