Etikettarkiv: nginx

Docker med WordPress

Ni som läser denna blogg vet hur förälskad jag är i Docker. Jag tänkte nu försöka förklara hur du kan köra WordPress tillsammans med Docker. Det är ingen lätt process men det finns en stor uppsida:

  • Flexibilitet – Möjlighet att flytta komponenter mellan servrar lätt. Exempelvis lyfta ur databasmotorn eller webbservern.
  • Säkerhet – Allt separeras med hjälp av Linux Containers. Inte lika säkert som separata fysiska servrar eller virtuella maskiner.
  • Skalbarhet – Att växla upp delkomponenter är snabbt och enkelt. Lägga till och ta bort memcached exempelvis.
  • Driftsättning – Gå från utveckling, stage-miljö till driftsättning går snabbt och smidigt. Inga jobbiga beroenden som saknas eller är felaktiga.

Men hur gör man då? Jo först och främst är det några saker man måste tänka på:

  • En docker med Nginx + WordPress
  • Skrivbart filsystem för wp-content utanför dockern till WordPress.
  • En docker med MySQL (eller MariaDB, Percona)
  • Skrivbart filsystem för MySQL-databasen utanför dockern
  • Framtid: En docker med memcached.

Då sätter vi igång. Jag går ej igenom hur du installerar Docker utan det kan du läsa här eller köra Vagrant som jag gör på Mac OS X.

Installera NginxNginx

Den första dockern vi skapar ska ha Nginx samt WordPress installerat. Port 80 för http ska exponeras utåt.

Först och främst kör vi igång kommandotolken bash i Ubuntu 13.10 samt installerar Nginx.

# mkdir -p /data/wordpress/

Först enligt ovan kommando så skapar vi en gemensam katalog för våra containrar samt värdsystemet som ligger under /data.

# docker run -v /data/wordpress:/data/wordpress -p 80:80 -i -t ubuntu:13.10 /bin/bash
# apt-get update
# apt-get -y dist-upgrade
# apt-get -y install php5-fpm php5-gd php5-mysqlnd nginx php5-cli php5-curl php5-json

Ändra sedan /etc/nginx/sites-enabled/default och lägg till konfigurationsdirektiv enligt exempelvis den konfigg-template du hittar här. Du kan även konfigurera tonvis med andra inställningar i Nginx för att uppnå optimal prestanda, men det är ligger utanför denna guide.

Du måste även sätta root till den delade katalogen /data/wordpress/ i Nginx-konfen samt lägga till nedan i /etc/nginx/nginx.conf:

daemon off;

Vi avslutar dockern genom att trycka ctrl-D eller skriva exit.

Sedan kör vi följande för att spara ändringarna vi har genomfört i vår docker. Obs detta är viktigt annars går allt förlorat:

# docker ps -a

Kontrollera sedan vilket container ID den dockern vi just jobbade med och skriv ner ändringarna permanent genom en commit:

# docker commit 5d jonaslejon/nginx-wp:version1

Det räcker att skriva exempelvis de första två tecken i container ID. Ovan exempel så skriver jag bara 5d.

WordPress installationwordpress

Nästa steg är att ladda hem och installera WordPress. Detta görs genom att vi ansluter till dockern som vi just installerade Nginx på:

# docker run -v /data/wordpress:/data/wordpress -p 80:80 -i -t jonaslejon/nginx-wp:version1 bash

Sedan installerar vi wget samt går vi till root-katalogen för webbservern vilket i mitt fall är enligt följande:

# apt-get -y install wget
# chown www-data /data/wordpress/
# cd /data/wordpress/
# wget http://sv.wordpress.org/wordpress-3.8.1-sv_SE.tar.gz
# tar xvfz wordpress-3.8.1-sv_SE.tar.gz
# mv wordpress/* .
# exit

Då var WordPress och Nginx installerat. Och glöm framförallt inte att göra en commit på ändringarna:

# docker ps -a
# docker commit 7e6b550faa50 jonaslejon/nginx-wp:version3

Installation av MySQL, MariaDB eller Percona Server

Här ska vi inte glömma att skapa MySQL dockern i en helt ny docker och inte fortsätta med föregående Nginx-docker.

# mkdir -p /data/mysql

Först skapar vi en gemensam katalog där filerna till databasen ska leva kvar. Sen kör vi igång en docker och delar katalogen:

# docker run -v /data/mysql:/data/mysql -p 3306:3306 -i -t ubuntu:13.10 /bin/bash
# apt-get -y install mysql-server
# chown ubuntu /data/mysql
# vi /etc/mysql/my.cnf
# service mysql start
# echo "create database wordpress"|mysql -plösenord
# echo "GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY 'wplösenord'" | mysql -plösenord
# exit 
# docker ps -a 
# docker commit 1f9b38696a7f jonaslejon/mysql:version1

Ovan så ändrar du även i konfigg-filen /etc/mysql/my.cnf där datadir finns (jag gör det med vi). Ändra katalogen från /var/lib/mysql till /data/mysql/.

Jag skapar även ovan en ny databas med namnet wordpress samt en användare med namnet wordpress och lösenordet wplösenord.

Om allt sedan fungerar och du har gjort en commit så kan du testa denna docker med:

# docker run -v /data/mysql:/data/mysql -p 3306:3306 -i -t jonaslejon/mysql:version1 /usr/bin/mysqld_safe

Starta upp allt

Då var två stycken Docker-containers skapade. Vi ska nu starta upp dessa och hoppas på att allt går vägen. Skillnaden här är att vi anger -d så att containrarna läggs i bakgrunden:

# docker run -d -v /data/mysql:/data/mysql -p 3306:3306 -i -t jonaslejon/mysql:version1 /usr/bin/mysqld_safe
Det vi gör sedan är att titta med docker ps:
docker ps
Samt kontrollera loggarna från containern:
docker logs

Ser bra ut! Då ska vi starta upp webbservern Nginx:

# docker run -v /data/wordpress:/data/wordpress -p 80:80 -i -t jonaslejon/nginx-wp:version3 sh -c "service php5-fpm start && service nginx start"
Verifiera att allt körs med hjälp av docker ps-kommandot.

Avslutande anmärkningar

Nu behöver du bara konfigurera WordPress genom att surfa till localhost:80. Detta står även under PORTS när du kör docker ps.

IP-adressen som du behöver när du konfigurerar WordPress-installationen till MySQL-databasen kan du få ut genom att köra inspect på rätt container:

# docker inspect c6e0c1e4e5f0|grep -i ipaddress
 "IPAddress": "172.17.0.2",

Om du ansluter via Vagrant mot containrarna så måste du även konfigurera i Vagrantfile alternativt när du kör vagrant up på följande sätt:

# FORWARD_PORTS=80,3306 vagrant [up|reload]

Övrigt

  • Du behöver inte ha en delad /data-katalog som jag kör med. Men bra om du vill ha data som ska leva en längre tid.
  • Du kan även köra Nginx och MySQL på samma container.
  • Supervisord kan vara bra att använda för att starta upp och hålla koll på processer.
  • Det finns färdiga containers i det centrala docker-indexet. Sök genom kommandot docker search wordpress eller klicka här >
  • Det finns ett fiffigt sätt att automatiskt koppla ihop två containers genom att använda -link argumentet. Då läggs miljövariablar innehållandes port samt IP-nummer till automatiskt på följande sätt:

docker link

Gillar du detta blogginlägg? Donera gärna till min Bitcoin-adress nedan eller dela detta inlägg i sociala medier.

  • 13cxyC2sFvNfAAShcAaSs2YMW3Q4ygstD4

Bättre prestanda med Unix domain sockets

Ett sätt att öka prestandan när det gäller kommunikation internt inom ditt eget system är att använda Unix domain sockets. Istället för att använda TCP för att kommunicera internt mellan processer på ditt system så bör du med fördel använda Unix-sockets då detta påverkar prestandan positivt.

Några exempel på där du kan använda Unix-sockets är i Redis samt om du använder Nginx och PHP-FPM. För att använda Unix-sockets i Redis behöver du enbart lägga till följande rad i redis.conf:

unixsocket /tmp/redis.sock

Och för att använda denna socket när du ansluter kan variera lite beroende på vilken klient du använder, men på följande sätt gör jag:

$redis->connect(’/tmp/redis.sock’);

Glöm inte att rättigheterna på /tmp/redis.sock måste vara så att både Redis samt klienten kan läsa. Nu över till hur man konfigurerar Nginx och PHP-FPM att använda sockets.

Första steget är att konfigurera FPM att lyssna på en socket, och detta görs i konfigurationsfilen. Min återfinnes här:

/etc/php5/fpm/pool.d/www.conf

Och i denna fil ändrar jag där raden listen återfinnes så det ser ut något i stil med:

listen = /var/run/php5-fpm.sock

Och nästa steg är att ändra så att Nginx vet att vi har en Unix-socket för PHP-exekvering och det kan göras genom att lägga till eller ändra din ”upstream” om du använder en sådan:

upstream php {
        server unix:/var/run/php5-fpm.sock;
}

Och sedan använda fastcgi_pass php på följande sätt till varje server:

     location ~ \.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                include /etc/nginx/fastcgi_params;
                fastcgi_intercept_errors on;
                fastcgi_pass php;
        }

Vill du fördjupa dig ännu mer gällande Unix sockets kan du läsa här. MySQL och PHP skall enligt manualsidan automatiskt välja Unix sockets om det finns tillgängligt vilket det bör göra standardmässigt.

WordPress prestanda 101

Under Sweden Social Web Camp så försökte jag på kort under en session tid förklara hur man kan analysera och hitta flaskhalsar i WordPress gällande prestanda. Så därför försökte jag här sammanfatta det jag pratade om på några rader.

Först och främst så bör du stänga av alla plugins och då se om prestandan fortfarande är dålig, för tyvärr finns det många dåliga plugins (se här då Computer Sweden intervjuade mig och Nikke, år 2009).

Okej, nästa grej att testa är att slå på något cache-plugin i form av W3 Total Cache eller WP Super Cache. Du kan även testa att ”städa upp” i databasen då många plugins lägger temporär eller onödig information i databasen (kommentera om du vet något plugin som gör detta).

Använder du ett cache-plugin så bör du även installera memcached samt titta i källkoden längst ner på sidan hur många SQL-anrop som cachas, exempelvis (skriver WP Super Cache också ut detta?):

Object Caching 730/765 objects using memcached

En annan grej man kan testa är att använda strace direkt från kommandotolken i Linux tillsammans med PHP, ungefär så här:

$ cd /min/blogg/

$ strace php index.php

Så får du lite loggrader utspottade på skärmen och om det står still länge på ett ställe så ser du exakt vad som händer på den raden. Samt så bör du även testa Xdebug så kan berätta exakt vilken rad i PHP-koden som går långsamt, tar lite tid att installera och använda.

Du kan även titta i MySQL:s slow-log som kan aktiveras på eller hittas i /etc/mysql/my.cnf (sök efter log_slow_queries).

Sist men inte minst det som jag brukar göra är att lägga upp Varnish som en front-end proxy framför Apache exempelvis, detta är en helt mer eller mindre transparent lösning. Kom även ihåg att Apache slukar massor av minne jämfört med Nginx som istället kan användas till memcached. Detta är nog det bästa tipset jag kan ge samt att testa använda ett CDN.

Sen finns det så klart mycket man kan göra på själva sidorna som WordPress spottar ut (sprites, javascript etc), men det är utanför detta blogginlägg.

Uppdatering: Glömde skriva två saker som jag nämnde på sessionen, dels är det att använda sig av en OP-code cache typ APC eller eAccelerator samt så kan även URL-strukturen i WordPress slöa ner prestandan.

Ubuntu 10.10

För några dagar sedan så släpptes Ubuntu 10.10 eller ”The Maverick Meerkat” som releasen också kallas. Jag använder mestadels Ubuntu på serversidan och använder således server-versionen av Ubuntu utan grafiskt gränssnitt.

Uppgraderingen gick smärtfritt och tog cirka en timme med hjälp av följande kommandon:

  1. sudo apt-get install update-manager-core
  2. edit /etc/update-manager/release-upgrades och ändra Prompt=normal
  3. sudo do-release-upgrade

När uppgraderingen är färdig så är Nginx uppdaterad till version 0.7.67 som är den senaste stabila samt går det även att installera php5-fpm direkt via apt. Annat bra med maverick är att Redis paketet är version 2.0.0 istället för 1.2.0 som skeppas med lucid.

När uppgraderingen är klar så kan du köra kommandot lsb_release -a så bör det se ut enligt följande:

Distributor ID: Ubuntu
Description:    Ubuntu 10.10
Release:        10.10
Codename:       maverick
Ubuntu server 10.10 kan laddas hem här: ubuntu.com/server/get-ubuntu/download

Så kommer du igång med Nginx + PHP-FPM

Nginx är en supersnabb webbserver/proxy skriven av ryssen Igor Sysoev och används av exempelvis WordPress.com och Loopias höghastighetstjänst Autobahn. I dagsläget så använder ca 8% av världens webbservar just Nginx som webbserver eller front-end proxy.

Nginx är även mitt självklara val vid installation av nya servrar, men dock är installationen inte helt enkel eftersom det inte finns inbyggt PHP-stöd vilket är det primära programmeringsspråk jag använder vid webbutveckling. Nginx är således beroende av exempelvis PHP-FPM (FastCGI Process Manager for PHP).

Installation

Först och främst så ska vi lägga till dotdeb i vår sources.list genom följande kommando:

$ sudo sh -c ’echo ”deb http://php53.dotdeb.org stable all” >> /etc/apt/sources.list’

Lägg sedan till rätt nycklar:

$ gpg –keyserver keys.gnupg.net –recv-key 89DF5277

$ gpg -a –export 89DF5277 | sudo apt-key add –

Nu kan vi synkronisera paketlistorna:

$ sudo apt-get update

Sen måste vi lägga till några paketberoenden:

$ wget http://us.archive.ubuntu.com/ubuntu/pool/main/k/krb5/libkrb53_1.6.dfsg.4~beta1-5ubuntu2_i386.deb

$ wget http://us.archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu38_3.8-6ubuntu0.2_i386.deb

$ sudo dpkg -i *.deb

Och sist men inte minst så installerar vi paketen via apt:

$ sudo apt-get install php5-fpm php5-cgi nginx

Sen måste nginx konfigureras och lättast är att utgå från den standard-konfiguration som medföljer och återfinns i filen /etc/nginx/sites-available/default. Om du vill se hur min konfigg-fil ser ut kan du utgå från denna.

Starta sedan om php-fpm samt nginx om de inte redan startas:

$ sudo sh /etc/init.d/nginx restart

$ sudo sh /etc/init.d/php5-fpm restart

Om php5-fpm klagar om pm.min_spare_servers eller liknande så måste du eventuellt ta bort en kommentering i filen /etc/php5/fpm/php5-fpm.conf

Thats’s it! Återkommer om jag hittar något lättare sätt att komma igång med nginx och php-fpm.

Snabb guide till Varnish

Fick en förfrågan från John Angelmo (@veidit) att skriva lite om den supergrymma front-end cachen Varnish. Varnish utvecklas till stor del av företaget Linpro från Norge med hjälp av den danske FreeBSD-utvecklaren Poul-Henning Kamp.

I Sverige är Varnish populärt och används av exempelvis Aftonbladet och SvD. Varnish har en mängd intressanta features och ett mycket kraftfullt konfigurationsspråk som påminner om C.

Använder du Ubuntu som jag gör så är det bara att installera via APT:

$ sudo apt-get install varnish

Standard så lyssnar varnish på TCP port 6081 och skickar vidare förfrågningarna till port 8080 där du förväntas ha din webbserver såsom Apache eller nginx.

Konfigurationsfilen för varnish återhittas i katalogen /etc/varnish/ med filnamnet default.vcl. VCL är också benämningen på det konfigurationsspråk som används som stödjer bla inline C. Se denna PDf-presentation av PHK för mer info.

Det viktiga vi behöver känna till är hur vi pekar ut vårat backend och vilka filer vi vill lagra i cachen. I mitt fall så valde jag Varnish för att Apache drog på tok för mycket minne då exempelvis bara bilder, css och annan statisk information skulle visas.

Nedan konfigurationsfil pekar först ut backend, sedan så sätter den X-Forwarded-For http-headern för att underlägga loggningen i Apache.

Sen så defineras vad som skall chachas.

backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
remove req.http.X-Forwarded-For;
set    req.http.X-Forwarded-For = client.ip;
if (req.url ~ "^/css" || req.url ~ "^/images" || req.url ~ "^/facebox" || req.url ~ "^/avatars") {
return(lookup);
}
if (req.request != "GET" && req.request != "HEAD") {
return(pipe);
}
if (req.url ~ "^/feedlist.php" || req.url ~ "^/removefeed.php" || req.url ~ "^/feeds.php" || req.url ~ "^/addfeeds" || req.url ~ "^/42it" || req.url ~ "^/login.php"
|| req.url ~ "^/admin" || req.url ~ "^/settings" || req.url ~ "^/js/tinymce/" ) {
return(pipe);
}
if (req.url ~ "\.(jpg|jpeg|gif|png|tiff|tif|svg|swf|ico|css|vsd|doc|ppt|pps|xls|pdf|mp3|mp4|m4a|ogg|mov|avi|wmv|sxw|zip|gz|bz2|tgz|tar|rar|odc|odb|odf|odg|odi|odp|o
ds|odt|sxc|sxd|sxi|sxw|dmg|torrent|deb|msi|iso|rpm)$") {
return(lookup);
}
}

sub vcl_hash {
set req.hash += req.http.cookie;
}

Uppdatering: Varför jag ibland måste använda Varnish tillsammans med Apache istället för mitt förstahandsval Nginx är pga de invecklade .htacess-filer jag skapat.

LoadImpact för belastningstester

Har just genomfört några belastningstester på den nya redundanta miljön som huserar i två olika datorhallar i USA. Med nginx och Redis som står för prestanda så måste jag säga att det ser rätt bra ut:

Återkommer när tjänsten är öppen för bruk!

LoadImpact med Ragnar Lönn (grundare av bl.a Algonet) i spetsen hittas så klart på LoadImpact.com

”Loadimpact.com, a unique, fully automated online service for load testing of websites. It has been developed by Gatorhole AB, a company that offers products and services related to system/network performance testing and measurement. Load Impact is the most popular web site load testing service on the Internet today, with tens of thousands of users per month and a total of over 50,000 executed load tests since its launch in january 2009.”

Operation driftsäkerhet och hastighet

Just nu jobbar jag på att försöka få till en bättre driftsäkerhet samt hastighet på mina webbplatser. Detta innebär bl.a att tjänster flyttas om mellan mina minst sex servrar och att mjukvaror såsom Apache slängs ut till förmån för Nginx och Lighttpd.

Jag försöker minska antalet komponenter som kan gå fel och försöker införskaffa viss överkapacitet istället för att alltid ha lite för lite som det varit tidigare.

Detta kommer troligtvis att resultera i mindre brandsläckning och mer tid till utveckling av nya grymma tjänster. Har även för avsikt att sälja av ett antal mindre tjänster såsom TweetValue via exempelvis Flippa.com

Att skriva bra kod

På senare tid så lägger jag mer tid och kraft till att skriva bra (snygg) och snabb kod. Att optimera sin PHP-kod kan spara många millisekunder i exekveringen. Vad pratar jag om då? Jo det finns några bra tips:

Kolla igenom all din kod med xdebug för att hitta långsamma exekveringar/funktioner. Och använd med fördel memcached, Sphinx och eAccelerator. Kasta bort Apache och titta istället på nginx och lighttpd. Jag har tidigare skrivit om hur du optimerar MySQL.

Det lönar sig att göra rätt från början!

Lite uppdateringar

Men först! Tack Ted för tidningen RES. Och glöm inte att hjälpa till med att rescensera hotell på Hotellkartan.se, du kan även vinna en månads DN prenumeration. Ted har även blivit pappa, grattis!

**

to.ly har snart förkortat 20 000 url:er, imponerande.

**

Bloggy har snart 10 000 medlemmar, kul att fler får upp ögonen för mikrobloggar. Exempelvis så nämnade P3, Bloggy ett antal gånger i rikssänd radio.

**

I övrigt så håller jag på att konsolidera lite av mina servrar, har idag fem stycken och tänkte försöka få bort åtminstone två.

**

Testar Amazons affiliate-program samt Travelpartner via Admeta.

**

Kolla in denna PHP + NGINX guide: interfacelab.com/nginx-php-fpm-apc-awesome

**

Det går nu att logga in på TweetBackup.com direkt med sitt Twitter-konto (oAuth). Här kan du läsa hur du kan använda Twitter-konto som autentiseringsmetod.