Enabling PHPMailer in 2.x Docker Image

Hi! Going through the excellent documentation to get the 2.x environment up and running. Hit a snag that I wanted to look into - the docs suggest using the SMTP module for Drupal. That is by far my preferred solution to getting emailing working out of my instance, but that module now requires PHPMailer, which doesn’t appear to be included in the Docker image.

I could install it by pulling up a terminal in the Docker instance, but would like to maintain image upgradability without having to reinstall. Is it possible to resolve this new dependency requirement of the SMTP module by including it in the official Docker image? Am I missing any other obvious solution? Thanks.

1 Like

Small nitpick, the relevant docs for farmOS 2.x are at Email - farmOS 2.x Docs


Based on those docs you could install the module using commands like this;

composer require drupal/smtp
drush en smtp
e.g. with docker-compose
docker-compose exec www composer require drupal/smtp
docker-compose exec www drush en smtp

If you’ve followed the hosting instructions and used volume mounts for your /opt/drupal directory, the effect of those commands should persist across Docker image updates because the smtp module and phpmailer library are installed within that bind mount.

You’d configure the module by going to https://my.farmos.site/admin/config/system/smtp. That configuration would also persist between Docker image updates because it gets saved in the DB.

2 Likes

Hi @mikefarms - welcome to the farmOS community! :smiley:

It might be worth considering a feature request to add SMTP to the canonical image.

This could either be done at the install profile level in the farmOS composer.json, or in the Composer project template composer.json. The latter might make more sense, since SMTP is not a hard dependency of farmOS itself - and is more of consideration at the hosting level (downstream) - which is precisely what that Composer project template serves to provide. This would cover basic deployments, because that template is used by the Docker image, but it would also allow advanced deployments to make the decision to remove it if they want to take a different approach (by customizing/managing the project composer.json themselves).

@Symbioquine the commands you suggest would work, but they assume that the end-user is bind-mounting the entire /opt/drupal directory into the container. Our development environment instructions suggest this, but for “basic” production deployments it is recommended that you only bind-mount certain subdirectories (eg: /opt/drupal/web/sites), so that you can upgrade farmOS by pulling a new Docker image.

composer require drupal/smtp will pull in the module and dependencies into /opt/drupal/web/modules - but those will not be persisted after pulling a new farmOS Docker image, if you aren’t bind-mounting the whole /opt/drupal directory.

All of this speaks to the need for better documentation and recommendations for downstream hosts/users who want to add additional modules to farmOS more broadly, I think. It is easy to drop a module tarball into a bind-mounted sites/all/modules/... directory, but if that module has additional dependencies declared in its composer.json file (as @mikefarms described with the SMTP module), those will not be covered. There are plenty of ways to accomplish it, but it may still be worth us thinking through and documenting the “recommended” approach(es) - since someone who is not familiar with Drupal wouldn’t know where to start, and right now the considerations are a bit tangled up with how you are deploying/hosting/managing your instance.

Currently our “Installing farmOS” documentation outlines 2 “recommended” approaches to managing the farmOS codebase:

There are two supported approaches to deploying the farmOS codebase:

  1. Using Docker images.
  2. Using packaged releases.

The third way, which is not described in the docs, is “Using Composer”, which would be the “advanced” approach. I always expected we would need to add documentation for that approach eventually, and I think that may be the “right” way to recommend that people manage additional modules they want to add to their instances.

So I think we have two tasks at hand, based on this forum topic:

  1. Should we consider adding the SMTP module to our Composer project template, so that it’s available by default for basic deployments?
  2. Create an issue for documenting “advanced” Composer-based deployments.
1 Like
  1. Should we consider adding the SMTP module to our Composer project template, so that it’s available by default for basic deployments?

@mikefarms if you are interested in starting a pull request for this, we can discuss whether or not we want to in that thread. The change itself would just be simply adding a drupal/smtp line to the require section of this file: https://github.com/farmOS/composer-project/blob/2.x/composer.json

  1. Create an issue for documenting “advanced” Composer-based deployments.

I created this issue: https://www.drupal.org/project/farm/issues/3245733

@Symbioquine Thanks for the initial guidance on installing Drupal modules. It helped me move forward a couple of steps. Now I’m trying to diagnose my SMTP connect() failed issue when I’ve triple checked my credentials and confirmed connection works in another client. Slogging through better logging with PHPMailer. I’ll let you know if I get it working.

As @mstenta mentioned, I followed the “basic” production deployment without bind-mounting the entire /opt/drupal directory. It looks like SMTP module won’t persist.

@mstenta, Thanks for the detailed considerations in your reply. I’m intrigued by the Composer approach, especially because it seems to help tap into the extensive Drupal ecosystem more directly. That said, I think it’s worthwhile to consider making the Docker implementation work out of the box with ALL needed features on and working. FarmOS really philosophically requires outgoing email for even the simplest implementation. Same with uploading files. Same with SSL (though having that work out of the box is probably not as easy).

PHPMailer/SMTP and file storing on and configured by default (with docker bind-mounts supporting in the documentation and compose files) would really help. Those two hangups have added hours already to getting my basic local setup running (Ubuntu). It doesn’t help that I didn’t know Drupal at all (but learning!!).

I’m guinea pigging myself on all of this and I’ll submit a couple of options as I see them in issues and pull requests. I’m grateful for your thoughtful replies, and I’m excited to bring whatever “beginner’s mind” input I can.

3 Likes

That said, I think it’s worthwhile to consider making the Docker implementation work out of the box with ALL needed features on and working.

Agreed @mikefarms - our challenge is always around supporting multiple use-cases. There are different ways to set up all three of the pieces you mentioned (email, files, SSL) - and so at some level we can’t make those decisions for people. But, it might be worth having an even more “prepackaged” option that does set up all of those things in a more opinionated way.

Great input.

Another example re: “advanced” composer-based deployments is to build a docker image that extends the farmOS docker image itself with your own composer.json. I started an example of this workflow here: GitHub - paul121/farmos-docker-site: An example repository for maintaining a farmOS docker image of a custom site. I need to update this a bit but waiting unitl we have a stable farmOS release. This example also follows the practice of exporting and committing your Drupal config which makes it easier to work in a “development” environment that has the same state as your production farmOS site.

1 Like

Yeah, sorry if I misled you. I was just thinking of the “dev” configuration. However, as @mstenta described much better, it wouldn’t really be desirable to bind-mount the entire /opt/drupal directory if you value light-weight updates simply by pulling in a newer Docker image.

1 Like

Resurrecting this topic because I found myself in this exact situation (even with the same module/library combo, although I also want to install other modules that have additional dependencies).

Being a newbie to farmOS and the Drupal ecosystem, I would prefer keeping the “basic” production deployment for the time being so that upgrades are easy. This means only bind mounting /opt/drupal/web/sites. In that scenario, what would be a good way of installing library dependencies for modules added to sites/all/modules?

PS: I don’t mind running composer require in the docker container if it’s a one time thing when installing or upgrading the module.

1 Like

@Symbioquine uses a script within the docker-compose.yml to install modules when the container is started - it may slow down start time and will require a connection to the module repo on every start.

Actual configs for smtp are stored in the database, so it should work.

Here is an example from his development environment to install Asset_Link.

Bare in mind that example starts a development instance and the script overrides the default farmOS entrypoint script so will need to be modified for production image and your modules.

Maybe there are other considerations that I haven’t thought about, whether this is suitable for a production environment or not.

2 Likes

Thank you, that’s exactly what I was hoping for! I use Nomad for deployment but the idea remains the same: install things before jumping into the default image entrypoint. This solved my problem:

task “server” {

  driver = "docker"
                                      
  config {            
    image = "farmos/farmos:3.0.0-beta2"
    ports = ["http"]
    volumes = [
      "/data/compute/appdata/farmos:/opt/drupal/web/sites",
    ]                       
    command = "bash"                                                            
    args = [                                                                    
      "-c",
      "composer require drupal/smtp drupal/health_check_url drupal/oauth_login_oauth2 && drush cr && exec docker-entrypoint.sh apache2-foreground"
    ]
  }
3 Likes

I’ve actually moved away from doing module installation - i.e. the composer require part - at container startup…

The reason is that it makes the runtime a bit fragile because, as @Farmer-Ed noted, it requires an internet connection and a number of mid-size downloads that have additive failure rates.

I still think the “everything in the docker-compose.yml file” strategy can be valuable for those just getting started or experimenting, but now that farmOS has official documentation on managing farmOS+modules via composer, I would urge folks to move towards that strategy for most production use-cases.

4 Likes