Migrating urlsl.me and its Database to a New Server with docker
I have neglected to move my url shortening site urlsl.me or urlshortlink.me to my new server so I'm still paying for the old server, so I'll be detailing the process of migrating that service here.
First, I backed up the production database on the old server using pgAdmin
Then I recreated the database on my new server, so that I could then restore the data using the backup I had just made.
I took a look at the source code before I added the Dockerfile. I decided my backend was horrendous, so I took time to redo it. I created a service IShortLinkManager
which does everything the site needs for now.
public interface IShortLinkManager
{
public Task<ShortLink> CreateNewShortUrl(string longUrl);
public Task<ShortLink> GetShortLink(string key);
}
The implementation consumes a database context from EF Core UrlslContext
. I call the database as needed in the method implementations for storing or retrieving a ShortLink
.
public class ShortLinkManager : IShortLinkManager
{
private UrlslContext dbContext { get; init; }
public ShortLinkManager(UrlslContext urlslContext)
{
dbContext = urlslContext;
}
public async Task<ShortLink> GetShortLink(string shortKey) =>
await dbContext.ShortLink.SingleOrDefaultAsync(s => s.Short == shortKey).ConfigureAwait(false);
}
In Startup.cs dependency injection is used so that ShortLinkManager
is a service that can be consumed by the asp.net controller. ShortLinkManager
also has the dependency UrlslContext
, so I made that a service as well.
services.AddDbContext<UrlslContext>(o => o.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IShortLinkManager, ShortLinkManager>();
Then auto-generated a Dockerfile with VS and pulled my changes down on the new server.
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["UrlShortLink/UrlShortLink.csproj", "UrlShortLink/"]
COPY ["DataManager/DataManager.csproj", "DataManager/"]
RUN dotnet restore "UrlShortLink/UrlShortLink.csproj"
COPY . .
WORKDIR "/src/UrlShortLink"
RUN dotnet build "UrlShortLink.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "UrlShortLink.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "UrlShortLink.dll"]
After that I ran two simple commands to build the docker image and run a new container
sudo docker build -t fc/urlsl:2021-x-xx -t fc/urlsl:latest -f UrlShortLink/Dockerfile .
sudo docker run -d --name urlsl -p someport:80 --restart=always --add-host host.docker.internal:host-gateway fc/urlsl:latest
Using sudo docker ps
showed me that the app is running:
At this point I made a configuration file for nginx and softlinked it to sites-enabled
with ln -s sites-available/urlsl.me sites-enabled/urlsl.me
upstream urlslLoadBalance {
server localhost:someport;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name urlsl.me urlshortlink.me;
location / {
proxy_pass http://urlslLoadBalance;
# some more proxy headers....
}
}
Here's something interesting about nginx: you can put multiple server
s in the upstream
block and it will load balance automagically. You just have to specify the upstream
in proxy_pass
.
Then to make sure I didn't make any errors I used nginx -t
to test the config.
I edited my DNS records to point to the new server and finally, used certbot to obtain new certificates with
sudo certbot --nginx -d urlsl.me -d urlshortlink.me
sudo service nginx restart
At this point the page was live.
Note the padlock in the address bar. This means my certificates are working correctly.
See you next week!