iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers VPS plans with one-click Docker, NVMe storage and a 14-day free trial.
The reliable production pattern is a small Compose stack: PHP-FPM runs Laravel, Nginx is the only public web entry point, and database, Redis, queue workers, and the scheduler stay on a private Docker network. Build immutable production images, keep application code out of runtime bind mounts, persist database and uploaded files in named volumes, and run HTTPS with a certificate renewal process you can test.
This guide shows how to prepare an Ubuntu VPS, build the images, write a production Compose file, configure Nginx and Laravel, add queues and scheduled tasks, and operate updates without losing data.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
What the production stack should look like
Compose gives each concern its own service while providing private DNS through the Compose network. Containers can reach one another by service name, so PHP-FPM connects to db:5432 or db:3306 and Redis connects to redis:6379; neither database nor Redis needs a public port.
| Service | Responsibility | Publicly exposed? | Persistent data |
|---|---|---|---|
app |
PHP-FPM runtime, Laravel code, Artisan commands | No | laravel_storage mounted read-write |
nginx |
HTTP/TLS termination and static files; forwards PHP requests to app:9000 |
Ports 80 and 443 only | Storage mounted read-only; certificate files as needed |
db |
Application database | No | Database named volume |
redis |
Cache, queue, and optionally session backend | No | Named volume only when persistence is required |
worker |
Long-running queue:work process |
No | Shares Laravel storage |
scheduler |
Runs Laravel’s scheduled tasks | No | Shares Laravel storage |
Use a production Compose file separate from your development file. Development commonly bind-mounts the source tree and enables verbose debugging; production should copy reviewed code into an image, use production environment values, publish only the web ports, and define restart policies.
#1 Best Overall
- Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
- With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
- Wide Application: attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
- Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
- Economical &Reusable: Built durable materials with a long-lasting battery,our CAGIWIRU air duster it's a sustainable alternative to disposable air cans.
Prerequisites on the VPS and in the repository
- An Ubuntu VPS with a static IPv4 address and, if used, an IPv6 address.
- A DNS A and/or AAAA record pointing your hostname to the VPS.
- Git access to the Laravel repository and a way to supply production secrets without committing them.
- Docker Engine, the Docker CLI, Buildx, and the Compose plugin installed from Docker’s official Ubuntu apt repository.
- Laravel running on PHP 8.3 or newer, with the extensions required by the current Laravel 13.x documentation: Ctype, cURL, DOM, Fileinfo, Filter, Hash, Mbstring, OpenSSL, PCRE, PDO, Session, Tokenizer, and XML. Install the PDO driver that matches your database.
After installation, confirm the daemon with sudo systemctl status docker and verify the client and image execution with docker version and sudo docker run hello-world. Add your deployment user to the docker group only if you understand that membership grants root-equivalent control of the host.
Recommended repository layout
Keep deployment files versioned with the application, but keep secrets outside the image and repository.
Recommended Free Tools
docker/
production/
php-fpm/
Dockerfile
nginx/
Dockerfile
default.conf
compose.prod.yaml
.dockerignore
.env.production # stored on the VPS, not committed
The PHP image contains the complete application and its Composer dependencies. The Nginx image only needs the public web tree and its configuration. If your front end has a build step, add a separate builder stage that produces the compiled assets before the runtime stages are copied.
Build a production PHP-FPM image
Use deterministic Composer output
Install dependencies from the lock file with development packages omitted. A multi-stage build keeps Composer and compilation tools out of the final runtime image.
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --prefer-dist --no-interaction --no-progress --optimize-autoloader
COPY . .
RUN composer dump-autoload --classmap-authoritative --no-dev
FROM php:8.3-fpm-alpine
WORKDIR /var/www
# Install the libraries and PHP extensions your application actually uses.
RUN apk add --no-cache icu-libs libzip oniguruma libxml2
&& apk add --no-cache --virtual .build-deps $PHPIZE_DEPS icu-dev libzip-dev oniguruma-dev libxml2-dev
&& docker-php-ext-install bcmath intl mbstring opcache pcntl pdo_mysql xml
&& apk del .build-deps
COPY --from=vendor /app /var/www
RUN mkdir -p storage bootstrap/cache
&& chown -R www-data:www-data storage bootstrap/cache
USER www-data
EXPOSE 9000
CMD ["php-fpm", "-F"]
Replace pdo_mysql with the driver required by your database, such as pdo_pgsql. Add any extension your application or a package requires, then check the built image with docker compose -f compose.prod.yaml run --rm app php -m. The exact base image and operating-system libraries must match the extensions and libc assumptions of your code; Alpine is compact, but a Debian-based PHP image can be simpler for packages that do not support musl cleanly.
Rank #2
- Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
- Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
- Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
- Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
- Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth
Do not run php artisan config:cache while building the image if the values depend on production secrets. Cache configuration during deployment, after the runtime environment has been supplied.
Exclude development material with .dockerignore
.git
.gitignore
.env*
node_modules
vendor
storage/logs/*
storage/framework/cache/*
storage/framework/sessions/*
storage/framework/views/*
tests
.phpunit.result.cache
Dockerfile*
compose*.yaml
The ignore file reduces build context size and prevents local credentials, test artifacts, and stale vendor files from entering the build.
Create the Nginx image and virtual host
Nginx Dockerfile
FROM nginx:alpine
COPY public /var/www/public
COPY docker/production/nginx/default.conf /etc/nginx/conf.d/default.conf
The PHP-FPM container has the full Laravel tree; this image needs only the public tree because Nginx must never expose the project root. Uploaded files are supplied through a read-only storage volume.
HTTP configuration
server {
listen 80;
server_name example.com www.example.com;
root /var/www/public;
index index.php;
location ^~ /.well-known/acme-challenge/ {
alias /var/www/certbot/;
try_files $uri =404;
}
location /storage/ {
alias /var/www/storage/app/public/;
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_PROXY "";
fastcgi_pass app:9000;
}
location ~ /.(?!well-known).* {
deny all;
}
}
Replace the example hostnames with your real names. The document root must be /var/www/public; serving the repository root can expose .env and other sensitive files. The FastCGI upstream is the Compose service name, not an IP address.
Write the production Compose file
The following is a starting point for a PostgreSQL-and-Redis deployment. Change the database image, driver, and health check if your application uses another database.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
- 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
- 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
- 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
- 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
- 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.
services:
app:
build:
context: .
dockerfile: docker/production/php-fpm/Dockerfile
env_file: .env.production
volumes:
- laravel_storage:/var/www/storage
networks: [backend]
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "php-fpm -t >/dev/null 2>&1"]
interval: 30s
timeout: 5s
retries: 3
nginx:
build:
context: .
dockerfile: docker/production/nginx/Dockerfile
ports:
- '80:80'
- '443:443'
volumes:
- laravel_storage:/var/www/storage:ro
- certbot_webroot:/var/www/certbot:ro
- letsencrypt:/etc/letsencrypt:ro
depends_on:
app:
condition: service_healthy
networks: [backend]
restart: unless-stopped
db:
image: postgres:16-alpine
env_file: .env.production
environment:
POSTGRES_DB: ${DB_DATABASE}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
networks: [backend]
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks: [backend]
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
worker:
build:
context: .
dockerfile: docker/production/php-fpm/Dockerfile
env_file: .env.production
command: php artisan queue:work --sleep=3 --tries=3 --timeout=90
volumes:
- laravel_storage:/var/www/storage
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks: [backend]
restart: unless-stopped
scheduler:
build:
context: .
dockerfile: docker/production/php-fpm/Dockerfile
env_file: .env.production
command: php artisan schedule:work
volumes:
- laravel_storage:/var/www/storage
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks: [backend]
restart: unless-stopped
networks:
backend:
driver: bridge
volumes:
laravel_storage:
db_data:
redis_data:
certbot_webroot:
letsencrypt:
Compose variable interpolation reads the deployment environment and the file used by env_file. Keep .env.production readable only by the deployment account. Set APP_ENV=production, a strong APP_KEY, APP_DEBUG=false, the database host as db, the Redis host as redis, and correct queue and cache drivers. A depends_on health condition controls startup order only; it does not coordinate migrations or guarantee that an application is ready for every request.
Launch and configure the stack
- Copy the repository and production environment file to a protected directory on the VPS.
- Review the Compose file, image tags, exposed ports, secrets, and volume paths.
- Build and start the services:
docker compose -f compose.prod.yaml up --build -d. - Run migrations deliberately from the application image:
docker compose -f compose.prod.yaml exec app php artisan migrate --force. For a first deployment, confirm the database backup and migration plan before using--force. - Build Laravel’s configuration cache:
docker compose -f compose.prod.yaml exec app php artisan config:cache. Re-run it whenever configuration values change; clear a bad cache withphp artisan config:clearand rebuild. - If the application uses Laravel’s conventional public upload path, create its link with
docker compose -f compose.prod.yaml exec app php artisan storage:link, or keep the explicit Nginx/storage/alias shown above. - Check the services and recent output with
docker compose -f compose.prod.yaml psanddocker compose -f compose.prod.yaml logs --tail=100 app nginx worker scheduler.
Test the public health endpoint, a normal authenticated request, an upload, a queued job, and a scheduled task before declaring the deployment complete.
DNS, HTTPS, and certificate renewal
Create the DNS A/AAAA records first and wait for them to resolve to the VPS. Port 80 must be reachable for the HTTP validation flow described by Ubuntu’s Certbot documentation. Keep the ACME challenge location available even after TLS is enabled.
When Nginx is in a container, Certbot’s Nginx plugin cannot automatically edit a host configuration it cannot see. A practical arrangement is to run Certbot on the VPS in webroot mode, using a directory shared with the Nginx container:
- Bind the host directory used for ACME files to the
certbot_webrootvolume, or use a host path consistently in both the Compose file and the Certbot command. - Request the certificate with the webroot method for each hostname, then mount the resulting Let’s Encrypt directory read-only at
/etc/letsencryptin Nginx. - Add an HTTPS server block that listens on 443, references the certificate and key under
/etc/letsencrypt/live/your-hostname/, and redirects ordinary HTTP requests to HTTPS while leaving/.well-known/acme-challenge/reachable. - Run
sudo certbot renew --dry-runbefore relying on unattended renewal. After a renewal, reload the container withdocker compose -f compose.prod.yaml exec nginx nginx -s reload.
Certificates and private keys belong in a protected persistent location, not in an application image layer. If you prefer Ubuntu’s documented Nginx plugin, terminate TLS in a host-level Nginx reverse proxy and forward traffic to the Compose Nginx service on a private host port instead.
Rank #4
- 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
- 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
- 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
- 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
- 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
Firewall and network exposure
Allow SSH and the web ports at both the VPS provider and the operating-system firewall. For example, permit OpenSSH, TCP 80, and TCP 443, then enable the firewall only after confirming your SSH session remains allowed.
Docker warns that published container ports can bypass assumptions made by UFW or firewalld. Do not publish database, Redis, PHP-FPM, or internal metrics ports. Where host-level filtering is required, apply Docker-aware rules in the DOCKER-USER chain and verify the effective rules with a test connection from an untrusted network. A firewall rule that exists only in UFW may not protect a port published directly by Docker.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Persistence, uploads, and backups
Named volumes survive container replacement and are created when Compose brings the project up. They are not backups. Back up the database and user-uploaded files independently of the VPS and periodically test restoring them on a separate instance.
- Back up
db_datawith a database-native dump or a volume snapshot coordinated with the database. - Back up
laravel_storage, especiallystorage/app/public, on a schedule that matches the value of the uploads. - Keep backup credentials and encryption keys outside the application containers.
- If uploads become large or must be shared by multiple VPS instances, evaluate object storage rather than converting the entire application tree into a host bind mount.
Only PHP-FPM receives writable storage in this design. Nginx receives the same volume read-only, limiting the impact of a web-server compromise.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Laravel production settings that still matter in containers
- Use
APP_ENV=productionandAPP_DEBUG=false. Never expose a debug exception page on a public hostname. - Generate and protect a strong
APP_KEY; changing it can invalidate encrypted data and sessions. - Set database, cache, queue, mail, and filesystem endpoints to service names or approved external services, not
localhost. Inside a container,localhostmeans that same container. - Point the web server at
public/index.php. Do not moveindex.phpto the repository root. - Run
php artisan config:cacheas part of deployment and rebuild the cache after configuration changes. - Give queue workers a timeout shorter than the process manager’s stop grace period, and size worker concurrency for the VPS CPU and memory rather than copying a development value.
Safe updates and rollback
- Build a new image from a reviewed commit and retain the previous image tag for rollback.
- Take current database and upload backups before destructive or irreversible migrations.
- Run the migration plan once, from a single application container; do not let every worker attempt migrations on startup.
- Recreate services in a controlled order with
docker compose -f compose.prod.yaml up -d, then verify health checks and logs. - Exercise HTTP, HTTPS, login, uploads, queue processing, and scheduled commands.
- If the release fails, restore the previous image and application configuration. A database rollback may require a tested restore rather than simply reversing a migration.
Compose supplies the service lifecycle, but it does not provide zero-downtime deployment, traffic draining, migration locking, observability, or backup retention. Add those controls according to your traffic and data-loss tolerance.
Best Value
- 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
- 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
- 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
- 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
- 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.
Troubleshoot the failures that appear most often
Nginx returns 502 Bad Gateway
Confirm that the PHP-FPM container is running and listening on port 9000, that the upstream is exactly app:9000, and that both services are on the backend network. Inspect docker compose logs app nginx. A PHP process that exits immediately usually indicates a missing extension, invalid environment value, or a permissions problem in storage or bootstrap/cache.
Laravel reports it cannot connect to the database
Use DB_HOST=db (or your actual Compose service name), wait for the database health check, and verify that the credentials in .env.production match the database container’s initialization values. Restarting a database container does not change an already initialized named volume’s credentials.
Uploaded files return 404
Check that PHP-FPM and Nginx mount the same named volume, that the file exists under storage/app/public, and that the Nginx alias has the trailing slash shown in the configuration. Ensure the web process can read the files without granting Nginx write access.
Queued jobs never run
Verify that the worker service is healthy and remains running, that the queue connection points to redis or the intended backend, and that failed jobs and worker logs are being inspected. A web request succeeding does not prove that a worker is consuming jobs.
HTTPS renewal succeeds but users still see the old certificate
Renewal writes a new certificate; Nginx must reload it. Check the mounted certificate path inside the container, run the reload command, and confirm the certificate served on port 443 from an external network.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchCompose on a VPS versus a managed Laravel platform
Self-managed Compose is appropriate when you need control over the operating system, image contents, network topology, and deployment process and can own patching, backups, TLS, monitoring, and incident response. A managed platform such as Laravel Forge removes much of that host configuration work in exchange for platform constraints and an ongoing service cost.
| Decision axis | Compose on your VPS | Managed platform |
|---|---|---|
| OS and topology control | Full control of images, services, networks, and firewall rules | Constrained by the provider’s supported stack |
| Operations responsibility | You patch Docker and Ubuntu, renew certificates, monitor, and back up | More routine server work is handled for you |
| Deployment and rollback | You design image promotion, migration locking, and rollback | Usually supplied as platform workflows, with provider-specific limits |
| Scaling | You add VPS capacity, replicas, and a load-balancing plan | Scaling options depend on the platform and plan |
| Total cost | VPS plus your engineering and incident-response time | Platform fees plus any underlying infrastructure charges |
Choose the model that matches your operational capacity, not just the monthly server price.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

