Learn how to set up Docker on your Mac so you can get busy with server-side Swift today.
Working with server-side Swift is quite different from client-side Swift such as iOS and macOS for one large reason: macOS is very rarely used on servers. It’s possible to use macOS for your web server, but this usually only happens if someone desperately needs macOS features such as Xcode running on a remote server.
Instead, servers are primarily the domain of Linux, an open-source operating system that has some things – but not many! – in common with macOS. Swift was ported to Linux some time ago, but only some of Apple’s libraries have been ported, and even then aren’t still 100% complete.
As a result, the best way to ensure your server-side Swift code will work on your server is to build and run your code on Linux every step of the way. You can code on macOS if you want, it doesn’t really matter – but you do need to build and run on Linux, to ensure what you’ve written can be deployed to a real server.
If you aren’t already running Linux as your desktop operating system, there are four options you can take:
Of the four options, #3 is by far the most popular, and it’s what we’ll be using for this article. Docker is a free program you can install, it lets you create Linux containers that are pre-configured for running Kitura, and it blurs the lines between macOS and Linux because you can write your code on macOS and run it inside the Linux instance.
To get started with Docker, go to https://docs.docker.com/docker-for-mac/ and click “Get Docker for Mac (stable)” to download the latest version of Docker. When the DMG has downloaded, double-click it to open, then drag it to Applications. Once it has finished copying, browse to your Applications folder in Finder and double-click Docker to start it – you’ll be asked to enter your admin password in order to complete setup.
Note: this article is an excerpt from my book Server-Side Swift.
To make things simple for people starting server-side Swift, I’ve crafted one Docker command that does everything you need to create, start, and gain access to an environment where you can run your projects.
Once you’ve installed the Docker app and started it, you should see a whale icon in your Mac’s status bar - that shows the Docker virtualization system is running.
Now open a terminal and run these commands to create a directory on your desktop where you’ll store all your server projects:
cd Desktop mkdir server cd server
Note: It’s possible your terminal starts you at a different location. If you see “~” in there then the commands above are correct, but if you see “~/Desktop” or similar then you’re already in your Desktop directory and can skip the first command.
That creates a directory called “server” and changes into it so that it’s the current working directory. Now run this command:
docker run -itv $(pwd):/projects --name projects -w /projects -p 8089:8089 -p 8090:8090 -p 5984:5984 twostraws/server-side-swift /bin/bash
Yes, that’s quite a lot, but it’s because I’ve tried to cram everything into one!
What the command does is:
/bin/bash– the default Linux terminal.
When you run that command Docker will need to download all the components required to make the container work, including Ubuntu itself as well as my customizations. If you’re curious, my customized version updates all the software, adds Swift, Curl, CouchDB, and MySQL, ready for all the projects in my Server-Side Swift book, and is based on IBM’s own Docker container.
After a few minutes you’ll find yourself looking at a terminal prompt like this:
That means installation has now completed: you’re now in the “projects” directory inside the container. This is mapped to the current working directory, so if you create any files here you’re really creating files in the “server” directory on your Mac’s desktop, and if you change any files in macOS those changes will be reflected in the Docker container.
Using one Docker container for all projects isn’t the preferred way of working, but it’s fine for beginners. When you become more experienced you’ll start creating individual containers for each project, and indeed each part of a project, but the single-container approach makes life easier for now.
The command you ran bridged the network ports 8089, 8090, and 5984 inside the container to ports 8089, 8090, and 5984 on your Mac. What this means is that if you try access any of those ports on your Mac, you get seamlessly transferred to the container.
We did this because IBM’s Kitura server runs on port 8090 by default, so it allows us to test content directly from a web browser on your Mac. Port 5984 isn’t used until project two in the book, and 8089 isn’t used until project eleven, but we need to configure both them and 8090 now, when creating the container. You’ll see this in action soon enough!
Before we’re done, I want to show you a few important Docker commands to help you get into and out of your container.
Right now, you see a prompt like this one:
I say “like” because the string of letters after the @ sign will be unique to you – container IDs are created randomly. The # sign means you’re currently root, so you have full control over the virtual system, and we’ll be using that to install extra software later on.
Try running the command
exit now, and after a few seconds you’ll be back to your regular macOS terminal prompt. What you just did was quit your Docker terminal, which effectively terminates the container. It still exists on your disk, but because “/bin/bash” was the main process of the machine and we just quit it, the container will cease running.
Now that you’re back on the macOS terminal, run this command:
docker ps. This shows a list of running containers, and you’ll see it doesn’t show any containers. Instead, you’ll see just some column headers where information would be, such as “CONTAINER ID”, “IMAGE”, and so on.
The list is empty because it shows only running containers, and exiting our container stopped it from running. We can ask for a list of all containers, running or otherwise, with this command:
docker ps -a. Note the extra “-a” in there. This time you’ll see the “projects” container listed, and it will have the status “Exited”.
We gave our container the name “projects” so that it’s easy to refer to, so let’s start it now: run
docker start projects then wait a few seconds. You should see “projects” written back to your terminal window, then your regular macOS command prompt. That’s Docker’s extremely laconic way of saying “your container is now running.”
To verify that “projects” is active, try running the
docker ps again. This time you’ll see your container listed with the status “Up about a minute”, showing that it’s active. This time, though, it’s active without us having a Bash terminal inside, so we can carry on working inside the macOS terminal as if Docker weren’t there.
So, now we have a fully configured Kitura Docker container up and running, and it’s effectively invisible – you could quit the Mac’s Terminal app altogether and Linux would carry on running in the background. This is the preferred state for containers once you’ve finished development: you start them up, then forget about them.
Of course, sometimes you’re going to want to get back into the container to make changes. Later on, for example, we’re going to be installing MySQL inside the container so that we have access to a database. To do that, you need to attach to a container that’s running – to connect to its existing Bash terminal so you’re back at the root prompt.
To attach to the “projects” container, run this command:
docker attach projects. You might need to press Return a couple of times, but after a few seconds you should be back at the root prompt inside your container. During development – when you need to run builds frequently – I usually keep the container attached for easy access.
Tip: If you want to start your container and attach at the same time, use
docker start -i projects.
Now that you’re back inside the container, running
exit will make it terminate just like before. More commonly you’ll want to detach from the container, which means “get me back to my macOS terminal, but leave the container running.” This is done using two special keystrokes: Ctrl+p followed by Ctrl+q. These should be pressed one after the other rather than together.
When you press those two, you’ll immediately be returned to your macOS terminal, but the “projects” container will carry on running. You can attach again using
docker attach, then detach, attach, detach, and so on; it will just carry on running.
If you ever want to destroy the container, use
docker rm projects. If it’s currently running you’ll be told to stop it first, or add the
-f parameter to force removal.
One last thing before we’re done with Docker: once you’ve created your Kitura container, Docker automatically saves the image required to recreate it. This means you can create more containers from the same image – “ibmcom/kitura-ubuntu” – in just a few seconds, because Docker doesn’t need to download it again.
Once again, Docker really is the preferred approach to server-side Swift development. With the setup above, you’re able to write your code using your preferred macOS tools, test using your preferred macOS web browser, but build and run using Linux. This means you’re in the perfect position to transfer your code to a real server when you’re ready, without having to constantly transfer files along the way.
LEARN SWIFTUI FOR FREE I have a massive, free SwiftUI video collection on YouTube teaching you how to build complete apps with SwiftUI – check it out!
Paul Hudson is the creator of Hacking with Swift, the most comprehensive series of Swift books in the world. He's also the editor of Swift Developer News, the maintainer of the Swift Knowledge Base, and a speaker at Swift events around the world. If you're curious you can learn more here.