Utveckla med PHP och MySQL i docker

  • Martin Haagen

PHP är fortfarande år 2025 ett mycket populärt programmeringsspråk för att bygga webbapplikationer. Det är lättillgängligt, enkelt att hosta och relativt lätt att lära sig. Den största utmaningen som utvecklare är ofta att få en bra utvecklingsmiljö på plats. Ett vanligt tillvägagångssätt är att installera en färdigpaketerad miljö såsom MAMP, XAMPP eller WAMP. Jag är personligen inte särskilt förtjust i dessa lösningar eftersom de begränsar vilka versioner av de olika komponenterna du kan använda. Dessutom belastar dessa serverprogram datorn onödigt mycket.

Alternativet är att installera webbserver, MySQL och PHP var för sig och därefter konfigurera miljön manuellt. Det har vissa fördelar, såsom att hela PHP:s verktygskedja blir tillgänglig. Nackdelen är att det rör sig om flera program som kräver uppdatering och underhåll. Därför är jag inte heller helt nöjd med detta alternativ.

Ofta faller jag tillbaka till att använda Docker och köra applikationerna i containrar. Det gör det enkelt att skapa en miljö, uppdatera den och återskapa exakt samma miljö på en annan dator. Det enda som behöver installeras är Docker. Det är inte särskilt svårt, och med Docker följer dessutom Docker Compose, som är ett fantastiskt verktyg för att starta flera containrar samtidigt.

En skärmavbildning av programmet docker desktop
Docker desktop som har ett projekt med 5 körande containers

Innan vi fortsätter bör vi förklara vad avbildningar och containrar är. En avbildning är en mall för hur en virtuell maskin ska se ut – med operativsystem och alla installerade applikationer. En container är en körande instans av en avbildning. Det finns avbildningar för nästan alla applikationer du kan tänkas vilja köra. Ibland behöver en avbildning anpassas, vilket görs genom att skapa en ny avbildning som ärver från en befintlig version.

En avbildning kan skapas med hjälp av en Dockerfile.

 1# php.dockerfile
 2# Use php:8.2-apache as base image
 3FROM php:8.2-apache
 4
 5# Install your extensions
 6# Add mysqli 
 7RUN docker-php-ext-install mysqli 
 8# Install pdo if you need to use PHP PDO
 9RUN docker-php-ext-install pdo pdo_mysql 
10# Run docker-php-ext-enable command to activate mysqli 
11RUN docker-php-ext-enable mysqli 

I detta exempel skapar vi en egen avbildning baserad på PHP:s officiella avbildning. I denna finns Linux och en Apache-webbserver, men den saknar stöd för MySQL. Anpassningen innebär att vi installerar de komponenter som behövs (raderna 7 och 9) och till sist aktiverar vi den modul PHP behöver för att kommunicera med en MySQL-databas.

Vi kan bygga avbildningen med kommandot docker build. Därefter startar vi en container från avbildningen med kommandot docker start. Då är en enkel miljö igång men vi vill även ha en databas och några andra komponenter. Dessa kan också köras i Docker. När vi behöver flera avbildningar blir det snabbt krångligt att starta alla containrar manuellt. Här kommer Docker Compose in i bilden. Det läser in en annan fil, docker-compose.yml, och startar samt konfigurerar flera containrar åt oss. Enklare och smidigare. Låt oss titta på följande docker-compose.yml-fil:

 1services:
 2  php:
 3    build:
 4        context: .
 5        dockerfile: php.dockerfile
 6    container_name: php-container
 7    volumes:
 8      - ./src:/var/www/html
 9    ports:
10      - "8080:80"
11    networks:
12      - app-network
13
14  mysql:
15    image: mysql:latest
16    container_name: mysql-container
17    restart: always
18    environment:
19      MYSQL_ROOT_PASSWORD: rootpassword
20      MYSQL_DATABASE: mydatabase
21      MYSQL_USER: user
22      MYSQL_PASSWORD: userpassword
23    volumes:
24      - db_data:/var/lib/mysql
25    ports:
26      - "3306:3306"
27    networks:
28      - app-network
29
30  phpmyadmin:
31    image: phpmyadmin/phpmyadmin
32    container_name: phpmyadmin-container
33    environment:
34      PMA_HOST: mysql
35      MYSQL_ROOT_PASSWORD: rootpassword
36    ports:
37      - "8081:80"
38    depends_on:
39      - mysql
40    networks:
41      - app-network
42
43volumes:
44  db_data:
45
46networks:
47  app-network:
48    driver: bridge

Här definierar vi tre tjänster: PHP (rad 2-12), MySQL (rad 14-28) och phpMyAdmin (rad 30-41). Varje tjänst startas som en separat container. Vi definierar även volymer för datalagring och ett nätverk som containrarna kan använda för att kommunicera med varandra.

Låt oss titta närmare på en tjänstedefinition. Först specificeras vilken avbildning som ska användas. Det kan antingen vara en specifik avbildning, som mysql:latest, eller en build-sektion som beskriver hur en anpassad avbildning ska byggas – vilket vi gör med PHP.

Varje container behöver ett unikt namn. Man kan skapa flera instanser av samma avbildning, men varje instans måste ha ett unikt namn. Ofta behöver programvaran i containern konfigureras, och då är miljövariabler ett smidigt sätt. I MySQL (rad 19–22) och phpMyAdmin (rad 34–35) används miljövariabler som kan justeras vid behov. Här anges t.ex. vilka uppgifter som behövs för att ansluta till databasen.

Data i en container är inte beständig. Det är ett problem vid utveckling eftersom man vill kunna spara det man skapat. Genom att montera volymer i containern kan en yta utanför containern göras tillgänglig. För PHP (rad 8) monterar vi src-katalogen mot /var/www/html i containern (om katalogen inte finns kommer den att skapas). Då kan vi arbeta med filer i src och köra dem direkt via containern. Databasen använder en Docker-volym (raderna 24 samt 43–44), vilket är vanligt för binärdata som måste sparas.

Man kan bestämma vilka portar containrar ska exponera. För PHP mappas port 8080 på värddatorn mot port 80 i containern (rad 10). Det gör att vi kan surfa till localhost:8080 och komma åt webbservern. För databasen görs localhost:3306 tillgänglig (rad 26) och phpMyAdmin exponeras via port 8081 (rad 37). phpMyAdmin är ett populärt verktyg för att administrera MySQL-databaser.

Till sist ser vi att alla tjänster kopplas till nätverket app-network, vilket gör att de kan kommunicera med varandra. Det innebär t.ex. att ett PHP-script i PHP-containern kan ansluta till MySQL-containern.

Terminal som kör docker-compose up -d
Uppstart av flera containrar går fort

När konfigurationen är på plats kan du köra docker-compose up -d för att starta tjänsterna. Första gången tar det en stund eftersom avbildningarna laddas ner. Därefter går uppstarter snabbt. Du kan stoppa alla tjänster med kommandot docker-compose down eller via Docker Desktop.

Nu är allt klart. När tjänsterna är igång jobbar du med din PHP-kod i src-katalogen. Webbläsaren svarar på localhost:8080 och phpMyAdmin finns på localhost:8081.

Lycka till med din utveckling!

Nedladdningar

Du kan ladda ner mina filer här om du inte vill klipp och klistra: