[Shopify CLI](/docs/apps/build/cli-for-apps) lets you use your local environment to run your app during development. However, you might want to deploy your web app to test the functionality in a different environment, or deploy your app to a production environment to get it ready for [distribution](/docs/apps/launch/distribution). For example, when you embed your app in the Shopify admin or Shopify Point of Sale using [App Bridge](/docs/api/app-bridge/previous-versions/app-bridge-from-npm/app-setup), you need to host your app's pages so Shopify can display them in an iframe or mobile webview. In this guide, you'll learn how to deploy your [Shopify app template](/docs/apps/build/scaffold-app) for testing or production using your preferred hosting provider. You'll also learn the steps for building and running an app in production mode, without using Shopify CLI. > Note: > If you want to deploy your Shopify app to Render, then you can follow [the third-party guide](https://docs.render.com/deploy-shopify-app) instead of this tutorial. ## What you'll learn In this guide you'll learn how to prepare, deploy, and run your app in a different environment. You can also explore some [provider-specific examples](#examples) to help you get started: - Create a new app configuration - Set up your container and database - Build and run your app - Deploy your Shopify app configuration - Test your app ## Requirements - You've [created an app using Shopify CLI](/docs/apps/build/scaffold-app), or you've [migrated your app](/docs/apps/build/cli-for-apps/migrate-to-latest-cli) to work with Shopify CLI. - You've selected your hosting service, and your account is able to create and deploy apps on it. ## Step 1: Create an app configuration file Create or link your app to an `app.toml` file. We recommend that developers have one configuration for development, and a separate one for production. That way, you can continue to develop your app after deploying it, without affecting your production environment. 1. Either create a new configuration, or use an existing one: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="terminal"> RAW_MD_CONTENTshopify app config link END_RAW_MD_CONTENT</script> </div> </p> 2. Get the necessary environment variables to deploy your app: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="terminal"> RAW_MD_CONTENTshopify app env show END_RAW_MD_CONTENT</script> </div> </p> 3. Note down the `SHOPIFY_API_KEY`, `SHOPIFY_API_SECRET`, and `SCOPES` values. You'll need to set them as environment variables before you can run your deployed app. ## Step 2: Build your app > Tip: > If your hosting provider supports Docker containers, then you can skip this step because the template comes with a [Dockerfile](https://github.com/Shopify/shopify-app-template-remix/blob/main/Dockerfile) that builds the app. Most providers have a CLI that can handle the deployment. For more information, refer to your provider's documentation. The [Shopify Remix app template](https://github.com/Shopify/shopify-app-template-remix) comes set up with Vite, which can build the bundles you'll need to host your app. If your provider doesn't support Docker, then you'll need to build the app yourself. 1. Copy your app's code to your container. 2. Install the app's dependencies: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash" data-title="npm"> RAW_MD_CONTENTnpm ci END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="yarn"> RAW_MD_CONTENTyarn install --frozen-lockfile END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="pnpm"> RAW_MD_CONTENTpnpm install --frozen-lockfile END_RAW_MD_CONTENT</script> </div> </p> 3. Run the `build` script with your package manager. This will create a `build` folder in your project that contains the compiled app: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash" data-title="npm"> RAW_MD_CONTENTnpm run build END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="yarn"> RAW_MD_CONTENTyarn build END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="pnpm"> RAW_MD_CONTENTpnpm run build END_RAW_MD_CONTENT</script> </div> </p> With this, your app will be ready to run, but you'll still need to set up a few things before you can do that. ## Step 3: Set up your database Now you'll decide which database you'll use, and where to host it. There are several cloud platforms that provide specialized database containers. You can use whichever storage strategy you're most comfortable working with. By default, the Remix app template uses an [SQLite](https://sqlite.org/) database (through the [`@shopify/shopify-app-session-storage-prisma`](https://www.npmjs.com/package/@shopify/shopify-app-session-storage-prisma) package), which is automatically set up by Prisma when you run the `setup` script. After your database is set up, update the `/prisma/schema.prisma` file to point to it. We recommend [using an environment variable](https://www.prisma.io/docs/orm/prisma-schema/overview#example), to allow using a different database for development and production. Before deciding on which database to use, understand that the template default quickly sets you up for development but has the following limitations: - SQLite is file-based, so it must run in a container that provides filesystem access. - You can only use multiple web containers if you create a separate container or volume for the database. - It can be slower than more powerful systems like Postgres or MySQL for very large databases. > Caution: > Some hosting providers, such as [Fly.io](https://fly.io/), might put web containers to sleep when they're idle, which resets the disk and wipes the SQLite database. You can persist your data across redeploys by creating a separate volume for the database file. ### Encrypting data at rest While Shopify will always use HTTPS to transfer data securely to and from the app, we recommend that apps encrypt their session data at rest to add another layer of security to your data. Specifically, apps should encrypt the access tokens in their storage to prevent unwanted access to shop data, in case their database is compromised. Most cloud providers make it possible to encrypt your data in their containers by default. ## Step 4: Set up environment variables Apps created using Shopify CLI use environment variables for configuration. During local development, Shopify CLI provides the environment variables directly to the environment. However, to deploy your app, you'll need to set these values manually in your hosting provider. You'll need to set the variables that you [obtained previously](#step-1-create-an-app-configuration-file), along with some other values, in your production environment. For information on how to do that, refer to your provider's documentation. > Caution: > Some variables represent API secrets or secure keys. These variables should be stored securely as secrets in your production environment, and should never be committed to a repository. The following environment variables need to be provided: | Variable | Required | Description | | --- |:---:| --- | | `SHOPIFY_APP_URL` | Yes | The URL origin where the app will be accessed when it's deployed, including the protocol. This will be provided by your platform.<br/>**Example**: `https://my-deployed-app.fly.dev` | | `SHOPIFY_API_KEY` | Yes | The client ID of the app, retrieved [using Shopify CLI](#step-1-create-an-app-configuration-file). | | `SHOPIFY_API_SECRET` | Yes | The client secret of the app, retrieved [using Shopify CLI](#step-1-create-an-app-configuration-file). This value should be stored securely. | | `SCOPES` | No | The app's access scopes, retrieved [using Shopify CLI](#step-1-create-an-app-configuration-file). This is **optional** if you're using [Shopify-managed installation](/docs/apps/build/authentication-authorization/app-installation). | | `PORT` | No | The port on which to run the app. For apps built using the [Remix app template](https://github.com/Shopify/shopify-app-template-remix), this variable needs to be set to the same value as the `EXPOSE` value in the `Dockerfile`. Defaults to `3000`. | ## Step 5: Deploy your configuration Before running the app on your hosting provider, you'll need to update your Shopify settings by deploying your TOML file using Shopify CLI. 1. In the `shopify.app.*.toml` file for your deployment environment, set `application_url` to the same as the `SHOPIFY_APP_URL` environment variable: <p> <div class="react-code-block" data-preset="file"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script data-option="title" data-value="shopify.app.toml"></script> <script data-option="nocopy" data-value="true"></script> <script type="text/plain" data-language="toml"> RAW_MD_CONTENTapplication_url = "<SHOPIFY_APP_URL>" [auth] redirect_urls = [ "<SHOPIFY_APP_URL>/auth/callback", ] END_RAW_MD_CONTENT</script> </div> </p> 2. Deploy your configuration to apply the changes to Shopify: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash"> RAW_MD_CONTENTshopify app deploy END_RAW_MD_CONTENT</script> </div> </p> > Caution: > To continue developing your app, you'll need to switch back to your development environment by running `shopify app config use`. ## Step 6: Run your app > Tip: > If your hosting provider supports Docker containers, then you should deploy your app to your provider, typically using their CLI, instead of running `start`. The Dockerfile will set up and run the app when you deploy it. After you've set up your database and environment variables, you can run your app. 1. Run the `setup` script to create or update your database: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash" data-title="npm"> RAW_MD_CONTENTnpm run setup END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="yarn"> RAW_MD_CONTENTyarn setup END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="pnpm"> RAW_MD_CONTENTpnpm run setup END_RAW_MD_CONTENT</script> </div> </p> 2. Run the application with the `start` command: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash" data-title="npm"> RAW_MD_CONTENTnpm run start END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="yarn"> RAW_MD_CONTENTyarn start END_RAW_MD_CONTENT</script> <script type="text/plain" data-language="bash" data-title="pnpm"> RAW_MD_CONTENTpnpm run start END_RAW_MD_CONTENT</script> </div> </p> If the database or environment variables aren't set up properly, the `start` script will fail to run. Check your logs if your app fails to start after deploying it. ## Step 7: Test your deployed app After you update your app URLs in the Partner Dashboard, you can test your app in a development store to make sure that it's configured correctly. 1. In the [Partner Dashboard](https://partners.shopify.com), go to your app's **Overview** page. 2. In the **Test your app** section, click **Select store** and choose a store to test the app. ## Re-deploying your app As you continue developing your app, you can re-deploy it with the following steps: 1. Select your production app with Shopify CLI: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash"> RAW_MD_CONTENTshopify app config use END_RAW_MD_CONTENT</script> </div> </p> 1. Deploy your app configuration and extensions, if you made any changes: <p> <div class="react-code-block" data-preset="terminal"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script type="text/plain" data-language="bash"> RAW_MD_CONTENTshopify app deploy END_RAW_MD_CONTENT</script> </div> </p> 1. Stop your production server, and re-run the `build` and `start` scripts. ## Examples You can follow the steps above to deploy your app using any hosting provider you prefer that can run JavaScript apps. The following are instructions for some popular platforms: - [Fly.io](/docs/apps/launch/deployment/deploy-web-app/deploy-to-fly) - [Heroku](/docs/apps/launch/deployment/deploy-web-app/deploy-to-heroku) ## Next steps - Keep developing your app. When you make changes that you want to deploy to production, you can deploy your app again. - [Select a distribution method](/docs/apps/launch/distribution/select-distribution-method) for your app and distribute it to users.