惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
Cloudbric
Cloudbric
G
Google Developers Blog
博客园_首页
博客园 - 司徒正美
N
Netflix TechBlog - Medium
Recorded Future
Recorded Future
博客园 - 叶小钗
C
Check Point Blog
L
LangChain Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
酷 壳 – CoolShell
酷 壳 – CoolShell
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
Cyberwarzone
Cyberwarzone
Project Zero
Project Zero
V
Vulnerabilities – Threatpost
C
Cisco Blogs
Scott Helme
Scott Helme
Last Week in AI
Last Week in AI
博客园 - 聂微东
T
Threat Research - Cisco Blogs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Hacker News
The Hacker News
Forbes - Security
Forbes - Security
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
Cisco Talos Blog
Cisco Talos Blog
S
Schneier on Security
T
The Exploit Database - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
AWS News Blog
AWS News Blog
C
CERT Recently Published Vulnerability Notes
Google DeepMind News
Google DeepMind News
N
News | PayPal Newsroom
Help Net Security
Help Net Security
B
Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Tenable Blog
I
InfoQ
S
Securelist
V
Visual Studio Blog
U
Unit 42
博客园 - 【当耐特】
S
Security @ Cisco Blogs

Railway Blog

Where Railway is, and where it's going (Summer 2026) PaaS vs IaaS vs SaaS: What Each Means and Who Should Pick What in 2026 The Best Continuous Deployment Tools in 2026 The Best PaaS for Multi-Region Deployments in 2026 The Best Platforms for Monorepo Deployments in 2026 Compliance Isn't a Feature, It's a Posture What is BYOC (Bring Your Own Cloud)? A Developer's Guide for 2026 The Best Managed Kubernetes Hosting in 2026 The Best Container Registries in 2026 The Vanilla Cloud Tax: What Rolling Your Own on AWS Actually Costs What is a PaaS? A Developer's Guide for 2026 The Best Cloud Observability and Logging Tools in 2026 The Best PostgreSQL Hosting for Developers in 2026 The Best Multi-Region Hosting Platforms in 2026 The Best Platforms to Deploy AI Apps in 2026 (Not the Models, the Apps Around Them) The Agent-Native Cloud: What It Means and Why It Matters Incident Report: May 19, 2026- GCP Account Suspension Counting to 3 with a new builder processing 50M+ monthly builds Railway iOS preview now available via TestFlight Kill your onboarding: selling to 10,000+ new users a day Your AI wants to nuke your database. Guardrails fix that. Better Rails for Agents: A New Remote MCP and Railway Agent in the CLI Moving Railway's Frontend Off Next.js One command deploys, there's a Stripe APP for that From registrar to deployed: buying a domain inside Railway A letter to open source builders who deserve more Networking is a black box, we used eBPF to open it Heroku Walked So Railway Can Run Security Features Your Security Team Will Love Railway Runs Open Source, Now We're Funding It Railway raises $100M Series B to unburden the builders Deploy autoscaling services, AI Workflow automation, and LLM APIs Without Kubernetes Hosting Postgres with GeoLite2: a practical guide to IP geolocation, data loading, and updates Serverless functions vs containers: CI/CD, database connections, cron jobs, and long-running tasks Hosting Postgres with pgvector: provider tradeoffs, migrations, indexes, and tuning Introducing the Railway integration on Delve.co Secure Cloud Hosting for Compliance: A Practical Guide for Startups and Regulated Industries How G2X Unlocked Rapid Experimentation at Scale with Railway MindFort Runs 100+ AI Pen Testing Agents Without Their Previous $10k AWS Bill How Bilt's Marketing Engineering Team Delivers at Scale with Railway Railway Technology Partners: Earn Revenue on Templates You Didn't Build ~$1 Million Paid to Developers Who Built Railway Templates CI/CD for Modern Deployment: From Manual Deploys to PR Environments Kernel Powers 1,000+ AI Agents on $444/Month of Railway Infrastructure Deploy Full-Stack TypeScript Apps: Architectures, Execution Models, and Deployment Choices Railway vs Cloudflare: How Their Architectures Differ and When to Use Each Run Scheduled and Recurring Tasks with Cron Monitoring & Observability: Using Logs, Metrics, Traces, and Alerts to Understand System Failures Logs, Metrics, and Traces: What Does Each Signal Tell You? Server rendering benchmarks: Railway vs Cloudflare vs Vercel Top five Heroku alternatives Comparing top PaaS and deployment providers Pricing to Encourage Use The F in SOC2 stands for functional Deploy Together, Earn Together: Introducing Railway Partnerships How We Oops-Proofed Infrastructure Deletion on Railway Bring Back the Free Plan Railway MCP - Stateful, Serverful, Pay-per-use Infrastructure Hackathon: Winners Announced! Mark Your Calendar: Railway User Hackathon with Prizes Launching Railway's Affiliate Program Zero-Touch Bare Metal at Scale Ssh, We’re Announcing One More Thing! $1M for Open Source Introducing Central Station Speed Isn’t Just About Code, It’s About Where That Code Runs One-Second Deploys? We Didn’t Believe It Either Why We’re Moving on From Nix Railway V3: Faster and Cheaper How to Migrate from Cloudflare Pages to Railway Supercharging Directus on Railway with a Static Frontend How to Migrate from AWS Lambda to Railway Deploy Triton Inference Server on Railway How to Handle Database Connection Pooling Building a NestJS App on Railway Implement a GitHub Actions Testing Suite Scaling a SaaS application on Railway Building a SaaS application on Railway Deploy a Dart App on Railway, Part 2 Deploy a Dart App on Railway, Part 1 Implementing Feature Flags from Scratch Cron Jobs with Django and GitHub Actions Deploy Offen on Railway Queues on Railway Working with NX, Railway and CI/CD Automated PostgreSQL Backups Using GitLab CI/CD with Railway Migrating From Heroku To Railway Cron Jobs on Railway Deploy Beam on Railway Deploy Authorizer on Railway Deploying Monorepo Applications How to Backup and Restore Your Postgres Database How to Backup Your Redis Instance Deploy Cusdis on Railway Deploy Ghost on Railway Using Github Actions with Railway Deploy Calendso (cal.com) on Railway Self-hosted website analytics Use Notion as a CMS for your NextJS blog
Manually Optimize Deployments on Railway
Adeboye Daniel · 2024-12-13 · via Railway Blog

Avatar of Adeboye Daniel

Adeboye Daniel

Comparing Nixpacks, Dockerfile, and image deployments

Railway does a number of built in optimizations to make the average build on Railway as fast as possible. However, there are times where you would want to deploy an image with as little as possible to speed up your deployments.

In this article, we will also explore how to optimize our Dockerfile for a smaller image size, and finally, we’ll use GitHub Actions to automate our deployments on Railway.

Prerequisites

  1. Basic application (All templates will be provided).
  2. Basic understanding of Docker and Dockerfiles.
  3. Familiarity with GitHub and GitHub Actions.
  4. Basic understanding of Railway’s deployment process.

These are the steps that we will cover:

  • Deploying with Nixpacks
  • Deploying with a Custom Dockerfile
  • Tips for Optimizing Dockerfiles for Smaller Image Size
  • Deploying Directly from a Pre-built Image
  • Setting Up GitHub Actions for CI/CD

Deploying with Nixpacks

In this section, we'll deploy a simple blog application API built with FastAPI using Railway’s default builder, Nixpacks, and measure the build and deploy times. You can find the template for the app here.

Project Deployment Setup

In our blog application template you will notice a file called railway.json here’s what the file looks like:

{
    "$schema": "https://railway.app/railway.schema.json",
    "build": {
      "builder": "NIXPACKS"
    },
    "deploy": {
        "startCommand": "uvicorn main:app --host 0.0.0.0 --port $PORT"
    }
}

Let’s break down the above configurations:

  • $schema: It ensures that the file follows Railway’s configuration standards.
  • builder: We specified Nixpacks as the build system.
  • startCommand: We defined the command to start the app. Here, it uses Uvicorn to run the FastAPI app on the port provided by Railway.

To deploy the template:

  1. Fork the repository: Fork the template from GitHub.
  2. Link to Railway: Create a new Railway project and connect it to your forked GitHub repo.
  3. Hit Deploy: Click Deploy, and Railway will automatically use Nixpacks to build and package the app.

Build and Deployment Time

During deployment, Nixpacks managed everything, from installing dependencies to creating a deployable image. The process took 1 minute and 27 seconds—55 seconds for the build and 32 seconds for deployment. While this is manageable for small apps, larger applications may take more time. In the next sections, we’ll explore alternatives like Dockerfiles and pre-built images.

Nixpacks deployment time in Railway
Nixpacks deployment time in Railway

Deploying with a Custom Dockerfile

While Nixpacks simplifies deployment, using a custom Dockerfile offers more control over your build process. Dockerfiles allow you to optimize images for smaller sizes, faster builds, and improved efficiency—especially for complex apps that require custom configurations or dependencies.

Why Use a Custom Dockerfile?

  • Optimize for Speed: Minimize unnecessary steps and dependencies to improve build times.
  • Control the Environment: Specify the exact OS, runtime, and libraries your app needs.
  • Ensure Consistency: Use the same Dockerfile locally, in CI, and on production to avoid "it works on my machine" issues.

Project Deployment Setup

In our blog application template, you will notice a file called Dockerfile. Here’s what the file looks like:

# Use an official Python runtime as a parent image
FROM python:3.11-slim

# Set the working directory in the container
WORKDIR /app

# Copy the requirements.txt file to the working directory
COPY requirements.txt .

# Install the Python dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code to the working directory
COPY . .

# Expose the port FastAPI will run on
EXPOSE $PORT

# Define the command to run your FastAPI application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "$PORT"]

Let’s break down the above configurations:

  • FROM python:3.11-slim: Uses a lightweight Python 3.11 image to minimize the size of the container.
  • WORKDIR /app: Defines the directory in the container where all operations will be performed.
  • COPY requirements.txt: Copies the requirements.txt file into the container and installs all the required Python dependencies.
  • RUN pip install --no-cache-dir -r requirements.txt: Installs the Python dependencies, using the -no-cache-dir flag to prevent caching and keep the image size small.
  • COPY . .: Copies the rest of the application code to the container.
  • EXPOSE $PORT: Exposes the dynamic port on which the FastAPI app will run.
  • CMD: Defines the command to run the FastAPI app using Uvicorn, binding it to 0.0.0.0 and using the Railway-provided port.

To deploy the template:

  1. Fork the repository: Fork the template from GitHub.
  2. Link to Railway: Create a new Railway project and connect it to your forked GitHub repo.
  3. Hit Deploy: Click Deploy, and Railway will automatically use Nixpacks to build and package the app.

Build and Deployment Time

During the deployment of the template, our custom Dockerfile handled everything, and the entire process from initialization to deployment took a total of 15 seconds. The build took 11 seconds, and the deployment took 4 seconds. This is significantly faster and a huge improvement compared to the Nixpacks builder.

Dockerfile deployment time in Railway
Dockerfile deployment time in Railway

Tips for Optimizing Dockerfiles for Smaller Image Size

When it comes to Dockerfiles, a little optimization can go a long way. Smaller image sizes not only make your deployments faster but also minimize bandwidth and storage costs.

In this section, we will discuss some effective strategies to optimize your Dockerfile for a leaner build.

  1. Use a Smaller Base Image: Choosing a minimal base image, such as alpine or slim, can significantly reduce the overall size of your Docker image.
  2. Multi-Stage Builds in Docker: Multi-stage builds allow you to separate the build environment from the runtime environment, ensuring that only the necessary artifacts are included in the final image, which helps keep it lightweight.
  3. Minimize Layers: Reducing the number of layers in your image can lead to a smaller size. Combine multiple commands into single RUN instructions whenever possible.
  4. Use .dockerignore Files: Similar to .gitignore, .dockerignore files prevent unnecessary files from being included in the build context, helping to keep the image size down and improving build performance.

Deploying Directly from a Pre-built Image

Using pre-built images is one of the fastest ways to deploy your application, as it completely bypasses the need for building during the deployment process. Instead of building the application on each deployment, you can pre-build the Docker image and store it in Docker Hub. Railway can then pull the image directly from there, resulting in significantly faster deployment times.

Why Use Pre-built Images?

  • Faster Deployments: By skipping the build process, deployments are much faster, often taking just a few seconds to pull the pre-built image.
  • Consistency: Pre-built images ensure that you are deploying the exact same image across different environments, eliminating discrepancies that may occur due to different build environments.
  • Simplified CI/CD: Since the image is pre-built, you can streamline your CI/CD pipelines to focus on testing and deployment rather than building.

Creating and Deploying Pre-built Images

To create your own pre-built image, follow these steps:

  1. Clone Repository: First, clone the template repository to your local machine.

  2. Build and Push Image: Navigate to the directory of the cloned template. Then, build and push the image using Docker.

Once the image is successfully pushed, it will be available in your Docker Hub account, and you can go ahead to deploy the image on Railway.

To deploy the image:

  1. Link to Railway: Create a new Railway project and connect it to your image on Docker Hub. Railway docs for reference.
  2. Hit Deploy: Click Deploy, and Railway will now provision a new service for your project based on the specified Docker image.

Pre-built Image Deployment Time

During the deployment of the template, the entire process, from initialization to deployment, took a total of 6 seconds. This is significantly faster and a huge improvement compared to using the Nixpacks and Dockerfile builders.

Image deployment time
Image deployment time

Setting Up GitHub Actions for CI/CD

In previous sections, we compared using Nixpacks, a custom Dockerfile, and pre-built images for deploying on Railway. The fastest method was using pre-built images. In this section, I will show you how to automate the entire process in our CI/CD pipeline using GitHub and GitHub Actions.

Here's a breakdown of how our CI/CD pipeline will work, we will be creating two workflows:

  1. Pre-built image builder and publisher workflow
  2. Railway image deployment workflow

Let's walk through the setup of these workflows.

Pre-built Image Builder and Publisher Workflow

We will create a GitHub Actions workflow file named docker-image.yml inside the .github/workflows/ directory. This file will handle the building of the Docker image and pushing it to the container registry.

Here’s what your workflow should look like:

name: Build and Push Docker Image

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      # Checkout the code
      - name: Checkout code
        uses: actions/checkout@v3

      # Log in to the Docker registry
      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      # Build the Docker image
      - name: Build the Docker image
        run: docker build -t railblog-docker:${{ github.sha }} .

      # Tag the Docker image
      - name: Tag the Docker image
        run: docker tag railblog-docker:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/railblog-docker:latest

      # Push the Docker image to Docker Hub
      - name: Push the Docker image
        run: docker push ${{ secrets.DOCKER_USERNAME }}/railblog-docker:latest

Let’s break down the workflow:

  • The workflow is triggered by a push to the main branch.
  • We use the actions/checkout action to pull the latest code.
  • We log in to Docker Hub using GitHub secrets to securely store credentials.
  • The image is built, tagged with both the commit SHA and latest, and then pushed to Docker Hub.

💡

Note: Make sure you add DOCKER_USERNAME and DOCKER_PASSWORD to GitHub secrets.

Railway Image Deployment Workflow

We will create a GitHub Actions workflow file named railway-deploy.yml inside the .github/workflows/ directory. This file will handle the deployment of our pre-built images.

Here’s what your workflow should look like:

name: Deploy to Railway

on:
  workflow_run:
    workflows: ["Build and Push Docker Image"]
    types:
      - completed

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'  

      - name: Install Railway CLI
        run: npm install -g @railway/cli

      - name: Link Railway project and deploy
        env:
          RAILWAY_API_TOKEN: ${{ secrets.RAILWAY_API_TOKEN }}
          RAILWAY_SERVICE_ID: ${{ secrets.RAILWAY_SERVICE_ID }}
          RAILWAY_PROJECT_ID: ${{ secrets.RAILWAY_PROJECT_ID }}
          RAILWAY_ENVIRONMENT_ID: ${{ secrets.RAILWAY_ENVIRONMENT_ID }}
        run: |
          railway link --service=$RAILWAY_SERVICE_ID --project-id=$RAILWAY_PROJECT_ID --environment=$RAILWAY_ENVIRONMENT_ID
          railway redeploy --yes

Let’s break down the workflow:

  • Trigger: The workflow is triggered by the completion of the Build and Push Docker Image workflow.
  • Checkout Code: We use the actions/checkout action to pull the latest code from the repository.
  • Set up Node.js: We set up Node.js version 20 to ensure our application runs in the correct environment.
  • Install Railway CLI: The Railway CLI is installed globally, which is necessary for deployment tasks.
  • Link Railway Project: Using environment variables stored securely in GitHub Secrets, we link the local repository to the specified Railway project and environment.
  • Deploy: The railway redeploy --yes command is executed to deploy the latest changes to Railway.

💡

Note: Make sure you add RAILWAY_API_TOKEN , RAILWAY_SERVICE_ID, RAILWAY_PROJECT_ID and RAILWAY_ENVIRONMENT_ID to GitHub secrets.

Here’s what your GitHub secrets should look like:

View of GitHub secrets
View of GitHub secrets

Workflow Test Run

Push changes to the main branch to trigger the GitHub Actions workflow, then monitor the Actions tab for successful Docker image builds and Railway deployments.

Here’s the result of the pre-built image builder and publisher Workflow:

Workflow run time using pre-built image
Workflow run time using pre-built image

Here’s the result of the Railway image deployment Workflow:

Workflow run time using Railway image deployment
Workflow run time using Railway image deployment

Conclusion

In this article, we explored effective strategies to speed up deployments on Railway. We covered how to utilize Nixpacks, create custom Dockerfiles, and leverage pre-built images for quicker deployment times. Additionally, we set up GitHub Actions for CI/CD, which ensures a streamlined workflow. By implementing these techniques, you can enhance your development experience, minimize wait times, and efficiently manage complex applications.