Every few months, I find myself needing to set up a local copy of a WordPress site. Usually, to do local development of a custom plugin or WordPress API integration. The issue is that I’m not constantly doing it, so I usually forget one of the steps, resulting in me having to re-solve a problem I had already solved in the past. Finally, I’m going to document the whole thing on my site so I can have one place to go back to with all the steps.
Instructions
Download a copy of your site. Thankfully, most hosts will offer downloadable backups of your WordPress site. Even better, this backup tends to include the SQL backup and the full directory contents.
Create a new directory on your drive where you can host the Docker and WordPress files.
Note: It is probably best not to set up this directory anywhere you sync data with a cloud provider. WordPress directories can be massive, so no need to sync that with iCloud or Dropbox.
Place the below Docker composer file in the directory; you may have to edit the ports to open ones within your Docker environment. Once placed, run docker compose up -d to start the containers.
services:
wordpress_db:
image: mysql:latestvolumes:
- wordpress_db:/var/lib/mysql# Volume for Docker to store MySQL Datarestart: alwaysenvironment:
MYSQL_ROOT_PASSWORD: root_passMYSQL_DATABASE: db_nameMYSQL_USER: db_userMYSQL_PASSWORD: db_passports:
- "3308:3306"# Port format "<Local Machine>:3306" 3306 being the in container port for MySQLwordpress:
depends_on:
- wordpress_dbimage: wordpress:latestvolumes:
- ./wordpress_data:/var/www/htmlports:
- "8008:80"# Custom port for Wordpress siterestart: alwaysenvironment:
WORDPRESS_DB_HOST: wordpress_db# Will hookup host with wordpress_db containerWORDPRESS_DB_USER: db_userWORDPRESS_DB_PASSWORD: db_passWORDPRESS_DB_NAME: db_namevolumes:
wordpress_db: {}
wordpress_data: {}
Unzip the backup, and place the WordPress main directory (the directory with the wp-config.php, etc., files) inside a directory called wordpress_data within your working directory.
Open your SQL backup in a good text editor. You could use VIM or something else, but I tend to use BBEdit for these edits as it can quickly find and replace on large files.
Do a complete find and replace on the main domain for the WordPress site you are recreating. I tend to do the following replacements:
Import your SQL file with your choice of SQL editors or via the terminal.
Update your wp-config.php file to replace all the define calls with the below, which references your Docker compose file:
// a helper function to lookup "env_FILE", "env", then fallback
if (!function_exists('getenv_docker')) {
// https://github.com/docker-library/wordpress/issues/588 (WP-CLI will load this file 2x)
functiongetenv_docker($env, $default) {
if ($fileEnv =getenv($env .'_FILE')) {
returnrtrim(file_get_contents($fileEnv), "\r\n");
}
elseif (($val =getenv($env)) !==false) {
return $val;
}
else {
return $default;
}
}
}
// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
/** Database username */define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'example username') );
/** Database password */define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'example password') );
/**
* Docker image fallback values above are sourced from the official WordPress installation wizard:
* https://github.com/WordPress/WordPress/blob/1356f6537220ffdc32b9dad2a6cdbe2d010b7a88/wp-admin/setup-config.php#L224-L238
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
*//** Database hostname */define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
/** Database charset to use in creating database tables. */define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );
/** The database collate type. Don't change this if in doubt. */define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );
Now visit your new WordPress container, and your site should load mostly intact!
Troubleshooting
You usually will need to delete any cache plugin content for the site to fully work.
If you have Wordfence or other security plugins, it might be best to delete those to allow logins.
I’ve found sometimes after the move there is a lingering https rule that forces the site to serve as HTTPS. Editing your wp-config.php file to contain these two lines at the bottom above the require_once(ABSPATH . 'wp-settings.php'); line tends to resolve this issue.
Starting to dive into WidgetKit since I finally have an app that calls for that sort of functionality. Was pleasantly surprised when I found out Apple actually lists the compatible SwiftUI views for WidgetKit!
This is new “feature” from OpenAI is truly insane. The idea of letting a company like OpenAI into your banking and personal finance feels like the worst possibly privacy decision you can make. This feels fueled by the rise of these financial “gurus” on social media and OpenAI wanting in on the popularity. Even with OpenAI’s callout of privacy and the ability to remove financial data, I wouldn’t trust a company still figuring out their plan to profitability to honor the promise of fully removing your information and not using it to train future models or sell to third-parties.
The other night, an old Mac OS X feature popped back into my head that I used to love: Dashboard Web Clips. It is really sad that nothing like that really seems to exist anymore, especially with the huge improvements to Widgets on macOS. I understand that modern webpage markup is usually a mess, so a feature like this would be difficult to maintain over the years. This video does a great job explaining how Web Clips worked, and you get a nice stroll down Leopard memory lane!
Two months ago, I announced that I was reviving my first Mac app, Coords, and modernizing it for the first time in 11 years. This was a surprisingly challenging project, mainly due to SwiftUI and a back-and-forth App Store review process. The great part, though, even with all the work and rebuilding, I’m happy to see the app released with its new icon and modern features.
In 2015, I had already been developing iOS apps for about 5 or 6 years and was pretty confident with my skill set and ability to build compelling iOS apps for that time. However, on Mac OS X, I was very unsure about how a lot of app development worked. Sure, OS X shared a lot with iOS at a foundational level. AppKit, though, was such a bigger beast to work with compared to UIKit at that time, which made me feel less than confident with my skills for developing for the Mac. Worse so, I vaguely remember it being difficult to find good example code and explanations of AppKit techniques in 2015.
Fast forward, though, and now my own confidence levels have swapped. Many of my day jobs since 2015 have required me to build custom Mac applications for data processing. Over the years, I’ve been slowly building a stronger ability to develop for the Mac, and it has resulted in me being able to confidently re-build Coords. Better yet, this release isn’t just a rebuild and modernization, but includes many features I wanted to include in the original release but didn’t know how to go about developing them at that time.
One last thing. In the day and age of AI/vibe coding of apps, Coords really isn’t anything crazy special as it stands today. Any coding agent would be able to hammer out an app similar to Coords without much intervention by a developer. This is something I struggled with when I was trying to find motivation to work on the project. If I’m being honest, I still feel a bit of that struggle even after releasing it and planning future features or working on other projects. However, something in me still finds great joy in the actual problem-solving of coding without AI assistance. Researching documentation, finding a solution to your problem, even possibly finding other interesting topics in documentation while browsing, and finally writing all the code myself is still as fulfilling as it was back in 2015 when I first wrote Coords.
I’ve been banging my head against the wall with App Store rejections about this “bug” that I couldn’t reproduce where my menu bar actions apparently didn’t work. Turns out they did work, but because the view was hidden at some point during app review, the action looked like it didn’t do anything. So frustrating, but hopefully that is the last of the rejections.
Picked up the recent remaster of Star Wars Dark Forces and found the included behind the scenes information super interesting! Didn’t know LucasArts used AutoCad to layout levels to the game!
One of the things that I’m always rejected for when submitting an app to the Mac App Store is the inability to re-open a window once you close it. I’m so used to just opening it again by clicking the dock icon, so it never crosses my mind to build in support in the menubar. I really wish this was something SwiftUI would do out of the box. They already give you the Close button in the menubar, why not give us a basic Open button as well?
I know plus addresses has been around for a long time for email, but having just learned about it late last year it still amazes me how often I’ve been using it!
11 years ago, I wrote my first Mac app, Coords, and released it on the Mac App Store. It was the first time I had tried to develop for the Mac, having come from the rather straightforward world of iOS development in the 2010s. It was a simple utility app that allowed you to interact with Apple Maps and do some semi-complex tasks, such as adding simple circular overlays to markers and easily see location information such as decimal degrees, minutes, and seconds. While many websites included a lot of this functionality, even to this day I don’t think anything can beat native Mac apps.
After many years, I just abandoned the app to work on other projects. However, every year or so I would think back on the app and get an urge to rewrite it and bring it up to date with the latest in Mac OS features. Every year that idea popped into my head and so did about a dozen other app ideas which I tended to lean towards working on rather than rewriting something I had already built. Plus, somehow over the years I had managed to keep almost every scrap of code and failed project I had ever created with Xcode, except for the source code to this app. I have searched every hard drive, Time Machine backup, and zip of old projects and still haven’t been able to find any code for the project.
All that changed this year when planning some of my yearly goals. I wanted to work on bringing back one of my apps into modern macOS times, utilizing the latest in SwiftUI and some of the new Tahoe-style UI elements. I finally buckled down over the past weekend and started to re-write Coords from the ground up. I had the basic functions of the app rewritten and running smoothly after only a few hours of SwiftUI tinkering!
My goal is to release this app within the next month or two back to the Mac App Store, and for the first time on my own website. It has been great working on this app again, and I can’t wait to share (again) it once it is ready!
This is most certainly not the first Mac App I purchased on the Mac App Store back in 2009…makes me wonder what app sold itself to a random company to just be renamed and taken over?