Introdução

Ao instalar temas e plugins no WordPress via Docker - utilizando a imagem oficial do WordPress - é bem provável que apareça uma tela igual a essa abaixo:

Isso ocorre pois o WordPress não consegue descompactar o tema/plugin para a pasta wp-content de dentro do contêiner.

Dito isso, a única forma até então de instalar temas/plugins é baixando o zip manualmente pelo navegador e descompactando na pasta wp-content.

Entretanto, é possível corrigir isso, ajustando o Dockerfile e o docker-compose.yml.

Dockerfile

Para o Dockerfile, utilizando a imagem oficial do WordPress com apache e php 7.4:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM wordpress:php7.4-apache

ARG APACHE_RUN_PORT

RUN sed -i "s/80$/${APACHE_RUN_PORT}/" /etc/apache2/ports.conf \
    && sed -i "s/:80>$/:${APACHE_RUN_PORT}>/" /etc/apache2/sites-enabled/000-default.conf

RUN usermod -u 1000 www-data \
    && groupmod -g 1000 www-data

EXPOSE ${APACHE_RUN_PORT}

Na linha 3, informo o parâmetro APACHE_RUN_PORT para setar a porta do apache. Por default no docker-compose.yml, a porta é 8080.

Nas linhas 5 e 6, é feita a substituição da porta default 80 do apache para a porta 8080, configurado no docker-compose.yml.

Nas linhas 8 e 9 é alterado o ID do usuário e do grupo www-data para 1000. Isso é um workaround para resolver incompatibilidades com a permissão de arquivos e pastas em hosts Linux, o que impede também a instalação de temas/plugins do WordPress.

A princípio, não sei se o problema ocorre em hosts macOS e Windows.

docker-compose.yml

Por fim, para o docker-compose.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
version: "3.9"
services:
  wordpress:
    build:
      context: .
      args:
        APACHE_RUN_PORT: "8080"
    network_mode: host
    volumes:
      - ./:/var/www/html
    user: www-data
    environment:
      APACHE_RUN_USER: "#1000"

Como pode observar, o docker-compose.yml não possui link com nenhum contêiner mysql. Costumo rodar mysql em um contêiner separado, pois utilizo o mysql para outros projetos também.

Dito isso, eu não subo um contêiner mysql para cada projeto. E para funcionar corretamente a conexão com o banco, a opção network_mode é configurada como host, assim o contêiner WordPress consegue enxergar todas as portas disponíveis no host.

Dessa forma, não é necessário passar o mapeamento de portas no docker-compose.yml.

Como é para rodar apenas localmente, não vejo problemas em manter essa configuração.

Na linha 7, é possível alterar a porta 8080 para outra qualquer, caso já tenha algum serviço rodando na porta 8080.

Na linha 13, é configurado o ID do usuário default do apache (www-data) para o valor 1000, devido ao workaround comentado na parte do Dockerfile.

wp-config.php

Na pasta do projeto WordPress, é preciso setar a constante FS_METHOD para direct:

1
2
/* Adicione valores personalizados entre esta linha até "Isto é tudo". */
define('FS_METHOD', 'direct');

O valor direct obriga o WordPress a instalar temas/plugins por direct file I/O, possibilitando o acesso direto ao sistema de arquivos.

Lembrando que essas alterações são úteis apenas em local. Por motivos de segurança, não é recomendado usar direct em ambiente de homologação e produção.

No mesmo arquivo, para o WordPress se comunicar com o serviço mysql, altere a constante DB_HOST para 127.0.1.1. Caso contrário, o WordPress não consegue estabelecer conexão com o banco de dados.

1
2
/** Nome do host do MySQL */
define('DB_HOST', '127.0.1.1');

Resumo

Após a criação dos arquivos Dockerfile e docker-compose.yml, e com a configuração do FS_METHOD e do DB_HOST no wp-config.php, basta subir o contêiner com WordPress:

1
$ docker-compose up wordpress

Lembrando que não foi configurado nenhum contêiner mysql no docker-compose.yml. Dito isso, é importante ter um contêiner separado com o mysql rodando antes de subir o WordPress na máquina.

No meu ambiente local, tenho apenas um contêiner mysql rodando para diversos projetos. Para criar um com mysql:

1
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql

Caso prefira trabalhar com diversos bancos, basta adaptar o docker-compose.yml para linkar com um contêiner mysql separado.

Nesse caso, a documentação oficial do Docker pode ajudar.