<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kofi Oghenerukevwe H.</title>
    <description>The latest articles on DEV Community by Kofi Oghenerukevwe H. (@rukykf).</description>
    <link>https://dev.to/rukykf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F79696%2F5e3caa32-dfeb-4d56-b946-54346aeae101.png</url>
      <title>DEV Community: Kofi Oghenerukevwe H.</title>
      <link>https://dev.to/rukykf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rukykf"/>
    <language>en</language>
    <item>
      <title>Minimal Deployment of BTCPayServer in Testnet Mode with Electrum Wallet</title>
      <dc:creator>Kofi Oghenerukevwe H.</dc:creator>
      <pubDate>Tue, 16 Feb 2021 21:27:51 +0000</pubDate>
      <link>https://dev.to/rukykf/minimal-deployment-of-btcpayserver-in-testnet-mode-with-electrum-wallet-j0i</link>
      <guid>https://dev.to/rukykf/minimal-deployment-of-btcpayserver-in-testnet-mode-with-electrum-wallet-j0i</guid>
      <description>&lt;p&gt;BTCPay Server is a self-hosted opensource solution for receiving Bitcoin and Altcoin payments. BTCPay Server implements the same API as Bitpay so it's easy to switch over from one to the other. There are detailed instructions for setting up the BTCPay Server (for a production environment) on the BTCPay Server documentation available here: &lt;a href="https://docs.btcpayserver.org/"&gt;BTCPay Server docs&lt;/a&gt;. That said, a minimal setup of BTCPay server in testnet mode is a bit tricky and this post is here to document the steps I took when I had to do that a few weeks ago. To be clear &lt;strong&gt;The instructions in this post are not for setting BTCPay Server up in production. For production settings, see BTCPay Server's official documentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The notes here are just to supplement the Minimal Manual Deployment docs on BTCPay Server which can be found here &lt;a href="https://docs.btcpayserver.org/ManualDeployment/"&gt;Minimal Manual Deployment&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Bitcoin
&lt;/h3&gt;

&lt;p&gt;Using these commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BITCOIN_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0.19.1"&lt;/span&gt;
&lt;span class="nv"&gt;BITCOIN_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://bitcoin.org/bin/bitcoin-core-0.19.1/bitcoin-0.19.1-x86_64-linux-gnu.tar.gz"&lt;/span&gt;
&lt;span class="nv"&gt;BITCOIN_SHA256&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"5fcac9416e486d4960e1a946145566350ca670f9aaba99de6542080851122e4c"&lt;/span&gt;

&lt;span class="c"&gt;# install bitcoin binaries&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp
wget &lt;span class="nt"&gt;-O&lt;/span&gt; bitcoin.tar.gz &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BITCOIN_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BITCOIN_SHA256&lt;/span&gt;&lt;span class="s2"&gt; bitcoin.tar.gz"&lt;/span&gt; | &lt;span class="nb"&gt;sha256sum&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; - &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;bin &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;sudo tar&lt;/span&gt; &lt;span class="nt"&gt;-xzvf&lt;/span&gt; bitcoin.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /usr/local/bin &lt;span class="nt"&gt;--strip-components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="s2"&gt;"bitcoin-&lt;/span&gt;&lt;span class="nv"&gt;$BITCOIN_VERSION&lt;/span&gt;&lt;span class="s2"&gt;/bin/bitcoin-cli"&lt;/span&gt; &lt;span class="s2"&gt;"bitcoin-&lt;/span&gt;&lt;span class="nv"&gt;$BITCOIN_VERSION&lt;/span&gt;&lt;span class="s2"&gt;/bin/bitcoind"&lt;/span&gt;
&lt;span class="nb"&gt;rm &lt;/span&gt;bitcoin.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install .NET Core
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;-q&lt;/span&gt; https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; packages-microsoft-prod.deb
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;apt-transport-https
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; dotnet-sdk-3.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install NBXplorer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
git clone https://github.com/dgarage/NBXplorer
&lt;span class="nb"&gt;cd &lt;/span&gt;NBXplorer
git checkout latest
./build.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Electrum
&lt;/h3&gt;

&lt;p&gt;You can use Electrum to setup either a testnet or live wallet for use with BTCPay Server.&lt;/p&gt;

&lt;p&gt;Install Electrum with any of the steps available on their docs &lt;a href="https://electrum.org/#download"&gt;Electrum Installation Docs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install BTCPayServer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
git clone https://github.com/btcpayserver/btcpayserver
&lt;span class="nb"&gt;cd &lt;/span&gt;btcpayserver
git checkout latest
./build.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Long-running processes
&lt;/h2&gt;

&lt;p&gt;A quick note that Bitcoin, NBXplorer and BTCPay are long running processes that should ideally run in the background. So when you run &lt;code&gt;bitcoind&lt;/code&gt; for instance, it would take over your ssh session till you stop the process. If you don't want to run them in the background, you can consider using something like &lt;code&gt;tmux&lt;/code&gt; to manage different sessions if you plan on just running these commands and leaving them running in multiple windows of the same ssh session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a new session with&lt;/span&gt;
tmux new &lt;span class="nt"&gt;-s&lt;/span&gt; BTC

&lt;span class="c"&gt;# create a new window in a session with Ctrl + b, c&lt;/span&gt;
&lt;span class="c"&gt;# detach from session with Ctrl + b, d&lt;/span&gt;
&lt;span class="c"&gt;# re-attach to session with tmux attach-session -t BTC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run Bitcoin in Testnet and Background Mode
&lt;/h3&gt;

&lt;p&gt;To run Bitcoind in testnet mode&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bitcoind &lt;span class="nt"&gt;-testnet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run in the background using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bitciond &lt;span class="nt"&gt;-daemon&lt;/span&gt; &lt;span class="nt"&gt;-testnet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run NBXplorer in testnet mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/NBXplorer
./run.sh &lt;span class="nt"&gt;--chains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;btc &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup your testnet wallet with Electrum
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# start testnet electrum in the background&lt;/span&gt;
electrum daemon &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--testnet&lt;/span&gt; 

&lt;span class="c"&gt;# create a main wallet&lt;/span&gt;
electrum create &lt;span class="nt"&gt;--testnet&lt;/span&gt; 

&lt;span class="c"&gt;# load wallet&lt;/span&gt;
electrum load_wallet &lt;span class="nt"&gt;--testnet&lt;/span&gt;

&lt;span class="c"&gt;# get the master key of the wallet - you'll need this for your BTCPayServer store&lt;/span&gt;
electrum getmpk &lt;span class="nt"&gt;--testnet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run BTCPay Server in testnet mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/btcpayserver
./run.sh &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testnet &lt;span class="nt"&gt;--bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 &lt;span class="nt"&gt;--sqlitefile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mydb.db &lt;span class="nt"&gt;--chains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;btc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unless you're using Tor, you might need to setup a server like Apache or Nginx with an ssl certificate that forwards to BTCPay server on &lt;code&gt;port 8080&lt;/code&gt; because BTCPay server does needs you to access it through HTTPS&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup your BTCPay Server store.
&lt;/h3&gt;

&lt;p&gt;After BTCPay Server is launched, visit it at its url and create a store. Then integrate that store with your electrum Bitcoin wallet using the master key you got from Electrum earlier. &lt;/p&gt;

&lt;p&gt;See &lt;a href="https://docs.btcpayserver.org/WalletSetup/#create-a-new-wallet"&gt;Connect BTCPay Server Wallet&lt;/a&gt; in the BTCPay Server docs.&lt;/p&gt;

</description>
      <category>btcpayserver</category>
      <category>bitcoin</category>
      <category>dotnet</category>
      <category>nbxplorer</category>
    </item>
    <item>
      <title>Building with IBM Cloud: Setting up a Drupal 8 website</title>
      <dc:creator>Kofi Oghenerukevwe H.</dc:creator>
      <pubDate>Mon, 14 Dec 2020 15:04:16 +0000</pubDate>
      <link>https://dev.to/rukykf/building-with-ibm-cloud-setting-up-a-drupal-8-website-3kop</link>
      <guid>https://dev.to/rukykf/building-with-ibm-cloud-setting-up-a-drupal-8-website-3kop</guid>
      <description>&lt;p&gt;I recently learned about IBM's Cloud offering and I decided to try it out and write about it. My objective was simple. I would set up a basic Wordpress blog using any of IBM's PaaS offerings. I am familiar with Azure so I was going in with the intention of having a Wordpress blog on IBM's equivalent of Azure's App Service. The Wordpress blog would connect and communicate with a managed MySQL database service.&lt;/p&gt;

&lt;p&gt;You've probably guessed from the title of this post that things did not go as planned. IBM does not, at this point in time, offer a Managed MySQL service. And while I could have easily provisioned a virtual server and installed MySQL on it, I don't ever like to deal with the management of databases. I prefer to use managed database offerings because they make it easier for me to handle things like replication, backups, scaling etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Good Parts
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Great User Experience
&lt;/h3&gt;

&lt;p&gt;The user experience for IBM's Cloud offering is the best of all the cloud services I have used and tested, and at this point, I have tested all of GCP, AWS and Azure. I immediately liked how easy it was to estimate the costs of the services I was provisioning. I think IBM has done an exceptional job making a platform that is intuitive and easy to navigate. If you have any experience with cloud services, IBM cloud's UI will be easy to get into. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VCG6y0YH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b2hn8wgiv3xl471b1ahj.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VCG6y0YH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b2hn8wgiv3xl471b1ahj.PNG" alt="Alt Text" width="880" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple Account Billing
&lt;/h3&gt;

&lt;p&gt;IBM has this concept of a lite account. The lite account is what you get by default when you sign up on IBM cloud and it gives you access to certain free / lite services. These services have very limited capabilities and in fact, I could not provision the managed PostgreSQL service without upgrading my account to a pay-as-you go account.&lt;/p&gt;

&lt;p&gt;That said, I liked how clearly distinguished both account types were from each other and how easy it was to filter out services that were available to lite accounts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LlhFq1d9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p7wbv0dweobg4cvp4czt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LlhFq1d9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p7wbv0dweobg4cvp4czt.PNG" alt="Alt Text" width="880" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Not-So-Good Parts
&lt;/h1&gt;

&lt;p&gt;The fact that there was no managed MySQL offering easily meant that I was stuck with IBM's Databases for PostgreSQL offering.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;At this point, I should mention that there are third-party offerings for schematics that provision MySQL on existing Kubernetes clusters within IBM's cloud environment, but the setup for these offerings required more work than I was willing to put into my test run of IBM's cloud environment for this article. If you're familiar with Kubernetes and don't mind a little hassle, you can definitely use a lot of third-party schematics in IBM Cloud's catalog to provision things like MySQL, Wordpress, Drupal etc. I am not familiar with Kubernetes so this was not an option for me.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Foundry
&lt;/h3&gt;

&lt;p&gt;Since Drupal works well with PostgreSQL, and IBM has a managed PostgreSQL service, I decided to setup a Drupal site instead. IBM's equivalent of Azure's App Service is called Cloud Foundry. Cloud Foundry has pre-configured environments for running apps written in several languages like PHP, Java, Ruby etc. Some of these environments are managed by IBM, while others are managed by developer communities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l9l2UoE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/646al7c30ic560kpav95.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l9l2UoE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/646al7c30ic560kpav95.PNG" alt="Alt Text" width="880" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pushing Drupal's code into Cloud Foundry was easy. But Drupal requires the use of some PHP extensions that are not installed by default in the Cloud Foundry PHP Configuration so I needed a way to get Cloud Foundry to install these extensions. I was happy to find that you can in fact ssh into the Cloud Foundry environment.&lt;/p&gt;

&lt;p&gt;You can use either the UI or IBM Cloud's CLI tools to ssh into Cloud Foundry. If you plan to use the CLI tools, you would need to install the Cloud Foundry's &lt;code&gt;cf&lt;/code&gt; plugin which is not available by default in the &lt;code&gt;ibmcloud&lt;/code&gt; CLI for some reason.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pOXd5JUF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qrg29p74kc7r0f8gjpip.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pOXd5JUF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qrg29p74kc7r0f8gjpip.PNG" alt="Alt Text" width="880" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, while I could ssh into Cloud Foundry as a regular user, the user does not have &lt;code&gt;sudo&lt;/code&gt; access so I could not install the required PHP extensions. And I learned that there is no way to get &lt;code&gt;sudo&lt;/code&gt; access in Cloud Foundry public. I learned that there's a deprecated Cloud Foundry for Enterprise offering that gave you the ability to get &lt;code&gt;sudo&lt;/code&gt; access but....like I said, deprecated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Engine
&lt;/h3&gt;

&lt;p&gt;So Cloud Foundry was out. IBM cloud has another PaaS offering called Code Engine which is specifically for running container images. I tried to run the Docker Hub Drupal image with Code Engine but the setup kept failing and I have no idea why it was failing. I visited the public URL that was generated for the Drupal Project I created and the URL just kept loading and loading and.... It's almost like it was stuck in some loop and I don't think the problem was with the container because I was able to run the Drupal docker container on my local machine without any hiccups.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LCVV1MX1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cseufs50ck4jb75az69c.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LCVV1MX1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cseufs50ck4jb75az69c.PNG" alt="Alt Text" width="880" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Virtual Server for Classic
&lt;/h3&gt;

&lt;p&gt;I ended up needing to provision a virtual server where I had all the privileges I needed to install PHP, the required PHP extensions, and finally Drupal itself. IBM has several different types of virtual and bare metal server offerings on its cloud. I tried provisioning a couple of them and ended up with the "Virtual Server for Classic" Offering because it was the least complicated to setup and &lt;code&gt;ssh&lt;/code&gt; into.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QZZpk6cV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/krdb7olx951dnqazmg7m.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QZZpk6cV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/krdb7olx951dnqazmg7m.PNG" alt="Alt Text" width="880" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After provisioning the server, I was able to &lt;code&gt;ssh&lt;/code&gt; into the server and do whatever I wanted. I was eventually able to install Drupal 8 and Apache on it. But then the weirdest thing kept happening. After a while, say 2 hours, the server would get a &lt;code&gt;disconnected&lt;/code&gt; status and while the public IPs and URLs were still actively showing me the Drupal site I installed, I would no longer be able to &lt;code&gt;ssh&lt;/code&gt; into the server. I destroyed and created the server several times to try to understand what was happening but, I have not been able to figure it out at this point. The same thing happened each time. After a few hours, the server would get disconnected and I would loose ssh access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managed PostgreSQL
&lt;/h3&gt;

&lt;p&gt;IBM Cloud's Managed PostgreSQL offering, ideally should be in the &lt;em&gt;Good Parts&lt;/em&gt; section of this article but, that would ruin the structure of my story so...here it is.&lt;/p&gt;

&lt;p&gt;IBM's Managed PostgreSQL was a breeze to setup. It was easy to choose the version of PostgreSQL I wanted to install. They have versions 9.5 through 12 available. The database credentials were easy to find and change. The public and private endpoints were easy to find and it was very easy for me to connect to the offering through the public endpoint.  Ideally, I should have found a way to connect to the PostgreSQL service through its private endpoint, from within the virtual server I provisioned earlier but I was lazy so...&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding Thoughts
&lt;/h2&gt;

&lt;p&gt;I was not able to do what I set out to do when I was preparing to write this article. I ended up setting up a basic Drupal site with PostgreSQL DB instead of a Wordpress site with MySQL DB. That said, my experience of IBM Cloud was actually enjoyable, especially since I have never used it before now. They have a number of services that are still in beta and I will be checking to see how much better they get within the coming months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Notes and Links to Documentation
&lt;/h2&gt;

&lt;p&gt;If you're interested in using any of the services / tools I used for this process, here are some things to keep in mind.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Drupal 8 will work easily with PostgreSQL 9. You need a bit more extra setup and configurations to get it to work with a higher version of PostgreSQL. I can no longer remember why I opted to use Drupal 8 instead of the latest version - Drupal 9. But I am sure there was a reason. :)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For a complete list of PHP extensions required to run Drupal see the ext-* items in Drupal's composer.json &lt;a href="https://git.drupalcode.org/project/drupal/blob/8.7.x/core/composer.json"&gt;Click Here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are installing Drupal behind Apache on a virtual server, you would need to enable Apache's rewrite module and put some rewrite rules in your Apache site configuration file&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Directory /var/www/your_drupal_site&amp;gt;
     RewriteEngine On
     RewriteBase /
     RewriteCond %{REQUEST_FILENAME} !-f
     RewriteCond %{REQUEST_FILENAME} !-d
     RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
&amp;lt;/Directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Documentation for installing IBM Cloud CLI tools &lt;a href="https://cloud.ibm.com/docs/cli?topic=cli-getting-started"&gt;Click Here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation for installing the Cloud Foundry plugin for IBM Cloud CLI tools &lt;a href="https://cloud.ibm.com/docs/cli?topic=cli-ibmcloud_cli#ibmcloud_cf_install"&gt;Click Here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation for getting started with Cloud Foundry &lt;a href="https://cloud.ibm.com/docs/cloud-foundry-public/getting-started.html"&gt;Click Here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ibmcloud</category>
      <category>cloud</category>
      <category>drupal</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Integration Testing with NodeJs, Jest, Knex and SQLite In-Memory Databases</title>
      <dc:creator>Kofi Oghenerukevwe H.</dc:creator>
      <pubDate>Mon, 11 May 2020 18:31:52 +0000</pubDate>
      <link>https://dev.to/rukykf/integration-testing-with-nodejs-jest-knex-and-sqlite-in-memory-databases-2ila</link>
      <guid>https://dev.to/rukykf/integration-testing-with-nodejs-jest-knex-and-sqlite-in-memory-databases-2ila</guid>
      <description>&lt;p&gt;If you're using Jest to write integration tests (that hit the database) for your Node application, you'll quickly notice that it's tricky to isolate your tests if you're using only one test database.&lt;/p&gt;

&lt;p&gt;While Jest runs all tests in a single testsuite sequentially, it runs your testsuites in parallel (by default). This makes for faster execution times, but it also means that changes to your database in one testsuite could interfere with another test that's currently running in a different testsuite.&lt;/p&gt;

&lt;p&gt;An easy solution to this is to configure a new SQLite in-memory database for each of your testsuites or test-files. This way, a testsuite only makes changes to its own database without affecting the database being used by other running testsuites.&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll walk through a simple setup for using in-memory databases in your Jest testsuites and running your database migrations on them before each test using Knex. The code for this tutorial is available here: &lt;a href="https://github.com/rukykf/jest-sqlite-tutorial"&gt;https://github.com/rukykf/jest-sqlite-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your knexfile create a new connection for your test file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// knexfile.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:memory:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;useNullAsDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;migrations&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;seeds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;seeds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When instantiating Knex, specify that you want to use the &lt;code&gt;test&lt;/code&gt; config we just created in our &lt;code&gt;knexfile&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For instance, in a file &lt;code&gt;db-config.js&lt;/code&gt; we could do this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// db-config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;knex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./knexfile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;development&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, Jest will set &lt;code&gt;NODE_ENV&lt;/code&gt; to &lt;code&gt;test&lt;/code&gt; when you are running your tests.&lt;/p&gt;

&lt;p&gt;Then in your integration testsuites, you need to run your migrations on the in-memory database before executing any tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// users.test.js and db-config.js are in the same directory&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./db-config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// run the migrations and do any other setup here&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;select users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Now each of your testsuites will use a separate SQLite database. You still have to keep in mind that all the tests in a given testsuite will use one database.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>tdd</category>
      <category>sqlite</category>
    </item>
    <item>
      <title>Setting up PhpStorm to Work with Docker Compose, Xdebug and PHPUnit for Local Development</title>
      <dc:creator>Kofi Oghenerukevwe H.</dc:creator>
      <pubDate>Sat, 07 Dec 2019 14:28:46 +0000</pubDate>
      <link>https://dev.to/rukykf/setting-up-phpstorm-to-work-seamlessly-with-docker-compose-xdebug-and-phpunit-for-local-development-dob</link>
      <guid>https://dev.to/rukykf/setting-up-phpstorm-to-work-seamlessly-with-docker-compose-xdebug-and-phpunit-for-local-development-dob</guid>
      <description>&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Docker-compose, Dockerfile and XDebug&lt;/li&gt;
&lt;li&gt;
Configuring PHPStorm

&lt;ul&gt;
&lt;li&gt;Setup PHPStorm Run/Debug Configuration&lt;/li&gt;
&lt;li&gt;Setup PHPStorm PHP CLI&lt;/li&gt;
&lt;li&gt;
Setup PHPStorm to run PHPUnit tests within docker container

&lt;ul&gt;
&lt;li&gt;Setup PHPStorm to listen for XDebug&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Troubleshooting&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I decided to write this article because I was frustrated by how difficult it was to find all the information I needed to make these technologies work well together in a single article. I am hoping this resource can be a good reference for myself and for others who might run into the same issues that I ran into.&lt;/p&gt;

&lt;p&gt;In this article we'll go through the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up the PhpStorm IDE so we can start and stop our docker-compose containers from within the IDE&lt;/li&gt;
&lt;li&gt;Debugging our code with PhpStorm and Xdebug (with Xdebug installed in a docker-compose service container)&lt;/li&gt;
&lt;li&gt;Running our test-suite with PhpStorm and PHPUnit (with PHP installed in a docker-compose service container)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The information in this article should work well with PhpStorm version 2019.2 and up. Please be aware that some of the configuration options I am about to discuss are not available in certain older versions of PhpStorm. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Configurations for docker-compose.yml, Dockerfile and Xdebug
&lt;/h2&gt;

&lt;p&gt;The docker-compose.yml and Dockerfile configuration files I'm using for this article were created by Peter Fisher of &lt;a href="https://www.youtube.com/channel/UCjFs9wBGz4HlEJGUB6jzUmw" rel="noopener noreferrer"&gt;How to Code Well&lt;/a&gt; and slightly modified by me. You can get access to the original files from his &lt;a href="https://github.com/pfwd/freecodecamp-PHP-OOP" rel="noopener noreferrer"&gt;Freecodecamp PHP OOP course Github repository&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In the docker-compose file I'm using for this tutorial I have 3 services (2 database services and one web service) as you can see in this snippet:&lt;/p&gt;

&lt;p&gt;docker-compose.yml&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

version: '3'

volumes:
  mysql_data:
  mysql_data_test:

networks:
  dev_network:

services:
  web:
    build:
      context: .
    ports:
      - 8080:80
    volumes:
      - .:/var/www/html
      - ./dockerconfigs/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
      - ./dockerconfigs/php.ini:/usr/local/etc/php/php.ini
    environment:
      APACHE_DOCUMENT_ROOT: /var/www/html/public
      XDEBUG_CONFIG: remote_host=host.docker.internal
    networks:
      - dev_network
    restart: on-failure

  db:
    image: mysql:5.7
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=devDB
      - MYSQL_ROOT_PASSWORD=test
    networks:
      - dev_network
    restart: on-failure


  db_test:
    image: mysql:5.7
    volumes:
      - mysql_data_test:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=devTestDB
      - MYSQL_ROOT_PASSWORD=test
    networks:
      - dev_network
    restart: on-failure


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The web service from the docker-compose file above references this Dockerfile in its build context&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

FROM php:7.3-apache

LABEL maintainer="Peter Fisher"

RUN apt-get update          \
    &amp;amp;&amp;amp; apt-get install -y   \
        git                 \
        zlib1g-dev          \
        zip                 \
        unzip               \
        libxml2-dev         \
        libgd-dev           \
        libpng-dev          \
        libfreetype6-dev    \
        libjpeg62-turbo-dev \
        libzip-dev          \
    &amp;amp;&amp;amp; pecl install xdebug                                                             \
    &amp;amp;&amp;amp; docker-php-ext-install mysqli pdo_mysql iconv simplexml                                      \
    &amp;amp;&amp;amp; docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/  \
    &amp;amp;&amp;amp; docker-php-ext-configure zip --with-libzip                                                   \
    &amp;amp;&amp;amp; docker-php-ext-install gd zip                                                                \
    &amp;amp;&amp;amp; docker-php-ext-enable xdebug                                                          \
    &amp;amp;&amp;amp; apt-get clean all                                                                            \
    &amp;amp;&amp;amp; rm -rvf /var/lib/apt/lists/*                                                                 \
    &amp;amp;&amp;amp; a2enmod rewrite headers

RUN curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/bin

ENV PATH /root/.composer/vendor/bin:$PATH
EXPOSE 9000

WORKDIR /var/www/html


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Xdebug, PHP, PHP-CLI and Apache are installed in the Dockerfile for the web service. Also notice that Xdebug's port 9000 is exposed. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Configuring Xdebug
&lt;/h3&gt;

&lt;p&gt;In the web service for the docker-compose file I am binding a php.ini file from my host machine into the web service container. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

services:
  web:
    build:
      context: .
    ports:
      - 8080:80
    volumes:
      - .:/var/www/html
      - ./dockerconfigs/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
      - ./dockerconfigs/php.ini:/usr/local/etc/php/php.ini


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The php.ini file I am binding to the container has some configuration options for Xdebug added at the end like so: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[XDebug]
xdebug.remote_port=9000
xdebug.remote_enable=1
xdebug.remote_connect_back=1
xdebug.remote_autostart=1


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are other ways to configure xdebug besides modifying your php.ini file. Specifically you could use an xdebug configuration file or you could add the configurations for xdebug as an environment variable right in your docker-compose. In the docker-compose file I'm using for this article, I set the xdebug configuration for remote_host under the web service container like so&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 environment:
      APACHE_DOCUMENT_ROOT: /var/www/html/public
      XDEBUG_CONFIG: remote_host=host.docker.internal


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So putting everything together my PHP project in PhpStorm currently looks like this (it's a new Laravel project I scaffolded for this tutorial).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8caozn5bypftvy95y0xk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8caozn5bypftvy95y0xk.gif" alt="Gif showing an overview of the project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Configuring PhpStorm
&lt;/h2&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow these steps to create a new PhpStorm Run/Debug configuration.
&lt;/h3&gt;

&lt;p&gt;Right click on your docker-compose.yml file and select "Create docker-compose.yml..."&lt;br&gt;
&lt;a href="https://i.giphy.com/media/dwRWHvzpsANvOhxIgC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/dwRWHvzpsANvOhxIgC/giphy.gif" alt="Gif showing the right clicking of docker-compose.yml file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you don't see this create option, wait a bit and right click again. I observed that it takes a while to show up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A configuration box will pop up where you can modify some options. I usually change the name of my configuration to something more memorable and I like to check the force builds option. But you can leave the defaults. &lt;br&gt;
&lt;a href="https://i.giphy.com/media/J5kBBNynKdMSDUx0ZK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/J5kBBNynKdMSDUx0ZK/giphy.gif" alt="Gif showing the configuration setting for PhpStorm server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run your new run/debug configuration&lt;br&gt;
&lt;a href="https://i.giphy.com/media/Pk9RwTYaSU6QkIn2lV/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Pk9RwTYaSU6QkIn2lV/giphy.gif" alt="Gif showing the running of PhpStorm's new run/debug configuration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure PHPStorm's local server to point to your docker service by going to &lt;em&gt;File &amp;gt; Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; PHP &amp;gt; Servers&lt;/em&gt;. Add a new server and set the host to localhost and the port to whatever port you are publishing your docker-compose web service to.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In my case I am publishing my web service's port 80 to my host container's port 8080 so I'd be filling in 8080 for port. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the Use path mappings option since we are working with docker containers and map your project root on your host to your project root in the docker container.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/Q8UgtoB8CxhzQUcJ5B/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Q8UgtoB8CxhzQUcJ5B/giphy.gif" alt="Gif showing the configuration setting for PhpStorm localserver"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow these steps to configure PhpStorm's PHP CLI interpreter
&lt;/h3&gt;

&lt;p&gt;Go to &lt;em&gt;File &amp;gt; Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; PHP&lt;/em&gt; to configure PHP's CLI. Click the &lt;strong&gt;Add a new CLI interpreter from Docker, vagrant...&lt;/strong&gt; option. Then select docker-compose&lt;br&gt;
&lt;a href="https://i.giphy.com/media/QutcLJ8T8rTqsmcmqh/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QutcLJ8T8rTqsmcmqh/giphy.gif" alt="Gif showing the configuration setting for PhpStorm CLI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the docker-compose service that contains your PHP installation. For me, that's the web service. &lt;br&gt;
&lt;a href="https://i.giphy.com/media/LMndqUiQAGEsLXbjTS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LMndqUiQAGEsLXbjTS/giphy.gif" alt="Gif showing the configuration setting for PhpStorm CLI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/eHdAtjajk5KnLkjQCa/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/eHdAtjajk5KnLkjQCa/giphy.gif" alt="Gif showing the configuration setting for PhpStorm CLI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ensure to select the &lt;strong&gt;Connect to existing container&lt;/strong&gt; option. This is important if you're working with a separate container for your database and it ensures that PhpStorm has access to the network your containers are joined to. If you select the &lt;strong&gt;Always start a new container&lt;/strong&gt; option, then each time your run PHPUnit within PhpStorm, a new container that is not joined to any of your networks will be created. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow these steps to configure PHPUnit in PHPStorm
&lt;/h3&gt;

&lt;p&gt;Go to &lt;em&gt;File &amp;gt; Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; PHP &amp;gt; Test Frameworks&lt;/em&gt; and add a new &lt;strong&gt;PHPUnit by Remote Interpreter&lt;/strong&gt; configuration. In the dialog that comes up, select the CLI interpreter we created in the previous step from the drop-down.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/YpeyE7QwxQLTPs7EQK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/YpeyE7QwxQLTPs7EQK/giphy.gif" alt="Gif showing the configuration setting for PhpStorm's PHPUnit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you should be able to run your PHPUnit tests within PhpStorm without doing a docker exec into your service container. &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow these steps to get PHPStorm to listen for XDebug on the right port
&lt;/h3&gt;

&lt;p&gt;Go to &lt;em&gt;File &amp;gt; Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; PHP &amp;gt; Debug&lt;/em&gt; and ensure PhpStorm is listening for Xdebug on port 9000 and can accept external connections. Then ensure that PhpStorm is listening for debug connections.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/UQIqO9ZYEnR7I3MJAt/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/UQIqO9ZYEnR7I3MJAt/giphy.gif" alt="Gif showing the configuration setting for PhpStorm's xdebug"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Tg68JT7lN5qg8Lr5lF/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Tg68JT7lN5qg8Lr5lF/giphy.gif" alt="Gif showing confirmation that Xdebug is listening for debug connections"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If you find that you're not able to receive Xdebug connections then ensure your path mappings are in order see this step &lt;/li&gt;
&lt;li&gt;If you are using multiple containers in a network, ensure that your PHP CLI interpreter has the &lt;strong&gt;Connect to existing container&lt;/strong&gt; option set&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>php</category>
      <category>xdebug</category>
      <category>phpunit</category>
    </item>
  </channel>
</rss>
